Неактивна зіркаНеактивна зіркаНеактивна зіркаНеактивна зіркаНеактивна зірка
 

Розділ 15. Комбіновані типи

15.1. Структури

Для об’єднання однотипних даних використовуються масиви, але часто виникає потреба об’єднати елементи різних типів: наприклад сутність Студент характеризується прізвищем (літерний рядок), роком народження (коротке беззнакове ціле число), курсом (перелік), спеціальністю (перелік) тощо. Для опису такої сутності тип даних “масив” не підходить, а використовувати для цього незв’язані між собою змінні – недоцільно, оскільки для опрацювання даних про кількох студентів втрачається цілісність подання інформації та унеможливлюється контроль за її правильним опрацюванням.

Вирішити описану проблему можна за допомогою структурних типів та структур, які дають змогу поєднати в єдине ціле сукупність різнотипних даних.

15.1.1. Визначення структурного типу

Структури – це об’єднані дані, які логічно пов’язані між собою.

Структурний тип – це тип даних, що визначається користувачем і складається з набору елементів, які називаються полями.

Загальний вигляд команди визначення структурного типу та змінних – структур (квадратні дужки використовуються для позначення необов’язкового елементу синтаксичної конструкції):

struct [<ім’я>] {

   <список-полів>

} [<список-змінних>];

де ім’я структурного типу – необов’язкове. Якщо ім’я структурного типу не вказане, то визначається анонімна структура;

список-полів – список оголошень полів; оголошення поля аналогічне до оголошення змінних; список-полів має такий загальний вигляд (квадратні дужки використовуються для позначення необов’язкового елементу синтаксичної конструкції):

    <ім’я-типу> <ім’я-поля> [ , ..., <ім’я-поля> ];

    [...

    <ім’я-типу> <ім’я-поля> [ , ..., <ім’я-поля> ];]

Структура повинна містити принаймні одне поле. Назви полів у межах однієї структури повинні бути унікальними, але назву поля певної структури можна використовувати як ідентифікатор іншого ресурсу – змінної, типу, функції, поля іншої структури чи об’єднання. У різних структурах можна використовувати однакові назви полів.

<список-змінних> – оголошення змінних-структур.

Кожний блок визначення даних повинен закінчуватися символом “;” (крапка з комою).

15.1.2. Оголошення структур

У мові С, оголошуючи змінну-структуру, ім’я структурного типу потрібно використовувати лише разом з ключовим словом struct. Оголошення змінних-структур окремо від визначення структурного типу в мові С виглядає так:

// оголошення та визначення переліків

enum Courses { I=1, II, III, IV, V, VI };

enum Speciality { SA, FL, KN };

// оголошення структури

struct Student {

char              lastName[15];

unsigned          birthday;

enum Courses      course;

enum Speciality   spec;

};

// оголошення змінних-структур

struct Student s1, s2;

Як і для переліків, змінні структурних типів (змінні-структури) можна оголосити в команді визначення структурного типу:

// оголошення переліків

enum Courses { I=1, II, III, IV, V, VI };

enum Speciality { SA, FL, KN };

// оголошення структури

struct Student {

char              lastName[15];

unsigned          birthday;

enum Courses      course;

enum Speciality   spec;

} s1, s2;   // оголошення змінних-структур

Рекомендація: стилістично краще змінні оголошувати окремо від визначення типу.

У мові С++ ім’я структурного типу можна використовувати при оголошенні змінних-структур без ключового слова struct.

Наприклад, Student s1, s2;

Крім того, можна оголошувати структури неіменованих (анонімних) типів: ім’я типу не вказується, але при цьому можна оголошувати змінні:

// оголошення переліків

enum Courses { I=1, II, III, IV, V, VI };

enum Speciality { SA, FL, KN };

// оголошення анонімної структури

struct {

char              lastName[15];

unsigned          birthday;

enum Courses      course;

enum Speciality   spec;

} s1, s2;   // оголошення змінних-структур

де змінні s1 та s2 – структури неіменованого структурного типу.

Для структурного, як і для інших типів, можна оголошувати масиви структур та вказівники на структури. Доступ до елементів структури здійснюється як до масива.

Приклад 13.1. Оголосити масив із 25 елементів типу структура Student:

struct Student ms[25];

Якщо одне чи більше полів структури є структурою, то такі структури називаються вкладеними.

Єдиним обмеженням при визначенні вкладених структур є те, що при визначенні структурних типів не допускається рекурсія, тобто при визначенні поля не можна використовувати ім’я даної структури ні безпосередньо ні через інші типи:

struct A {

   struct A x;  // помилка: поле x структури A не може мати тип цієї ж структури

};

Єдиний виняток з цього правила – коли поле є вказівником на таку структуру:

struct A {

   struct A *y;  // допускається

};

15.1.3. Розподіл пам’яті для структур

У пам’яті для структури виділяється неперервна ділянка, розмір якої дорівнює сумі розмірів усіх полів з урахуванням вирівнювання. При цьому розмір області пам’яті, виділеної для структури, може бути більшим за суму розмірів полів цієї структури.

Поля, вказані при визначенні структури першими, розташовуються в комірках з молодшими адресами.

Розглянемо, що таке вирівнювання і як воно працює.

Для структури

struct A {

   char a;

   int b;

} x;

її розмір (sizeof(A) чи sizeof(x)) не завжди буде дорівнювати 5, все залежить від налаштування компілятора та директив у тексті програми.

 

Правило вирівнювання: поля у пам’яті вирівнюються по межі, кратній своєму розміру.

Згідно цього правила, 1-байтові поля не вирівнюються, 2-байтові – вирівнюються до позиції парних адрес, 4-байтові – до позиції адрес, кратних чотирьом і т.д.

Переважно за замовчуванням вирівнювання розміру структури в пам’яті становить 4 байти. Таким чином, sizeof(A) == 8:

(Для ознайомлення з повним текстом статті необхідно залогінитись)