Масив є сукупністю елементів одного типу, а структура є сукупністю елементів різних типів.
Оголошення структури має наступний формат:
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; // помилка: невідповідність типів