Структури мови C

Масив є сукупністю елементів одного типу, а структура є сукупністю елементів різних типів.

Оголошення структури має наступний формат:

 

struct struct_name

{

type1 member1_name;

type2 member2_name;

typeN memberN_name;

};

 

Структура оголошується за допомогою ключового слова struct, за яким слідує необов'язкове ім'я нового типу даних (struct_name) та у фігурних дужках шаблон, за яким створюватимуться об'єкти структурного типу. Шаблон містить послідовність оголошень членів структури, кожне з яких завершується крапкою з комою.

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

Наприклад:

 

struct address

{

char* name; // ім'я "Іваненко Петро Миколайович"

char* street; // вулиця "Зелена"

int house; // номер дому 15

int flat; // номер квартири 2

char* town; // місто "Лисичанськ"

char* region; // область "Луганська"

int zip; // індекс 93107

};

 

Тут оголошується новий тип користувача з іменем address, який задає шаблон для створення об'єктів поштової адреси, прийнятої в Україні.

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

Змінні типу address можна оголошувати точно так, як і будь-які інші змінні.

Ініціалізувати змінні struct можна так само, як масиви. Наприклад:

 

address ipm =

{

"Іваненко Петро Миколайович",

"Зелена", 15, 2,

"Лисичанськ",

"Луганська",

};

 

Об'єкти структурного типу можуть присвоюватися, передаватися як фактичні аргументи функцій і повертатися функціями як результат їх виконання. Наприклад:

 

address current;

address set_current(address next)

{

address prev = current;

current = next;

return prev;

}

 

Інші операції, наприклад, порівняння (== та !=), для структурних об'єктів не визначені. Проте користувач може сам визначити ці операції.

Розмір об'єкту структурного типу не обов'язково рівний сумі розмірів всіх його членів. Це відбувається з тієї причини, що архітектури деяких комп'ютерів вимагають розміщувати об'єкти вбудованих типів в апаратно визначених межах (або просто тому, що робота при такому вирівнюванні буде ефективнішою). Типовий приклад - це вирівнювання цілого в| межах слова. В результаті вирівнювання можуть з'явитися "дірки" в структурі.

Структурний тип можна використовувати відразу після його оголошення, ще до того, як буде завершено його повне визначення. Наприклад:

 

struct link // елемент зв'язного списку

{

link* previous; // попередній елемент

link* successor; // наступний елемент

};

 

Проте нові об'єкти типу структури не можна оголошувати до тих пір, поки не з'явиться повне визначення структури. Тому оголошення:

 

struct no_good {

no_good member; // рекурсивне оголошення

};

 

є помилковим (компілятор не в змозі встановити розмір структури no_good).

Щоб дозволити двом (або більше) структурним типам посилатися один на одного, можна просто оголосити ім'я одного з них як ім'я деякого структурного типу. Наприклад:

 

struct list; // буде визначено пізніше

struct link

{

link* pre;

link* suc;

list* member_of;

};

struct list

{

link* head;

};

 

Якби не було першого оголошення list, оголошення члена member_of структури link привело б до синтаксичної помилки.

Можна також використовувати ім'я структурного типу ще до того, як тип буде повністю визначений, якщо тільки це використання не потребує знання розміру структури. Наприклад:

 

struct S; // S - ім'я деякого типу

extern S а;

S f();

void g(S);

 

Але приведені оголошення можна використовувати лише після того, як тип S буде визначений:

 

void h()

{

S а; // помилка: S не визначений, адже для виділення пам'яті

// потрібно знати розмір об'єкту

f(); // помилка: S не визначений, адже для повернення значення

// потрібно знати розмір об'єкту, що повертається

g(a); // помилка: S не визначений, адже для передачі аргументу

// потрібно знати розмір об'єкту, що передається

}

2.5.2.1 Вибір члена структури по імені об'єкту

Якщо відоме ім'я структурного об'єкту, звернення до окремих членів структури здійснюється за допомогою оператора “.” - вибір члена структури або класу по імені об'єкту. Наприклад:

 

address ipm;

ipm.name = "Іваненко Петро Миколайович";

ipm.house = 15;

 

2.5.2.2 Вибір члена структури через вказівник на структурний об'єкт

До членів структури часто звертаються через вказівник на структурний об'єкт, використовуючи оператор “->” - вибір члена структури або класу через вказівник. Наприклад:

 

void print_addr(address* p)

{

cout<< p->name << ‘n’

<< ”вул. “<< p->street << “, “ << p->house << “, “<< p->flat << 'n'

<< ”м. “ << p->town << 'n'

<< p->region << “ областьn”

<< p->zip << 'n';

}

 

2.5.2.3 Еквівалентність структурних типів

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

 

struct s1 {int а;};

struct s2 {int а;};

 

В результаті маємо:

 

s1 x;

s2 у = x; // помилка: невідповідність типів

 

Оскільки структурні типи також відрізняються від основних| типів, тому одержимо наступне:

 

s1 x;

int i = x; // помилка: невідповідність типів