Структури в сі

Теги: Сі структури, ініціалізація структури, ініціалізація вкладених структур, покажчик на структуру, вкладені структури, покажчики на вкладені структури, покажчики на поля структури, вирівнювання полів структури, pragma pack.







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

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

Всі літаки мають набір загальних властивостей в межах одного класу. Якщо ж нам треба більш точний опис, то можна виділити підкласи: літак амфібії, бойові винищувачі, пасажирські лайнери - і в межах вже цих класів описувати об'єкти. Наприклад, нам необхідно зберігати інформацію про співробітників компанії. Кожен співробітник, в загальному, володіє великою кількістю різних властивостей. Ми виберемо тільки ті, які нас цікавлять для розв'язання прикладної задачі: стать, ім'я, прізвище, вік, ідентифікаційний номер. Для роботи з таким об'єктом нам необхідна конструкція, яка б могла агрегувати різні типи даних під одним ім'ям. Для цих цілей в сі використовуються структури.

Полями структури можуть бути будь-які оголошені типи, крім самої структури цього ж типу, але можна зберігати покажчик на структуру цього типу:

У тому випадку, якщо кілька полів мають один тип, то їх можна перерахувати через кому:

Після того, як ми оголосили структуру, можна створювати змінну такого типу з використанням службового слова struct. Доступ до полів структури здійснюється за допомогою операції точка:

Структура, оголошена в глобальному контексті, видно всім. Структура також може бути оголошена всередині функції:

Можна спростити приклад: синтаксис мови дозволяє створювати екземпляри структури відразу ж після визначення:

Структура також може бути анонімною. Тоді ми не зможемо використовувати ім'я структури надалі.

У цьому прикладі ми створили змінну A. Вона є структурою з двома полями.

Структуру можна форматувати під час створення як масив. Поля в цьому випадку будуть присвоюватися по порядку.

Зауваження: таким чином можна тільки ініцалізіровать структуру. Привласнювати значення всієї структурі таким чином не можна.

Коли ми визначаємо нову структуру за допомогою службового слова struct, в просторі імен структур (воно не має нічого спільного з просторами імен С ++) створюється новий ідентифікатор. Для доступу до нього необхідно використовувати службове слово struct. Можна визначити новий тип за допомогою службового слова typedef. Тоді буде створений псевдонім для нашої структури, видимий в глобальному контексті.







Зауваження. Якщо ми створюємо новий тип-структуру, полем якого є покажчик на цей же тип, то його необхідно оголошувати явно з використанням службового слова struct

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

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

Структури в сі
Подання структури в пам'яті.

Перша структура повинна мати розмір 6 байт, друга 8 байт, третя 7 байт, проте на 32-розрядної машині компілятор VC зробить їх все три рівними 8 байт. Стандарт гарантує, що поля розташовані один за одним, але не гарантує, що безперервно.

Є можливість змінити упаковку структур в пам'яті. Можна явно вказати компілятору яким чином виробляти упаковку полів структури, об'єднань або полів класу. Яким чином це робити, залежить від компілятора. Один з найпоширеніших способів прагма pack ()

Використання #pragma pack не вітається: логіка роботи програми не повинна залежати від внутрішнього представлення структури (якщо, звичайно, ви не займаєтеся системним програмуванням або ламаєте чужі програми і мережі).

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

Цей приклад працює, але це хак, якого необхідно уникати. Правильно писати так

Привести масив до структури (або будь-якого іншого типу) за стандартом також неможливо (хоча в різних компіляторах є для цього інструменти).
Але в сі можливо все.

Але запам'ятайте, що в даному випадку поведінка не визначено.

Структура сама може бути полем структури. Приклад: структура Model - модель автомобіля, має назву, номер, рік випуску і поле Make, яке в свою чергу зберігає номер марки і її назва.

Вкладені структури започатковано як багатовимірні масиви. У попередньому прикладі можна зробити початкову ініціалізацію наступним чином:

P.S. подібним чином форматувати рядки не варто, тут так зроблено тільки для того, щоб спростити код.

Покажчики на поля структури визначаються також, як і звичайні покажчики. Покажчики на вкладені структури можливі тільки тоді, коли структура визначена. Трохи переробимо попередній приклад: "деанонімізіруем" вкладену безіменну структуру і візьмемо покажчики на поля структури Model:

Як вже говорилося раніше, в сі, навіть якщо у двох структур співпадають поля, але структури мають різні імена, то їх не можна приводити до одного типу. Тому доводиться позбуватися від анонімних вкладених структур, якщо на них потрібно взяти покажчик. Можна спробувати взяти покажчик типу char * на поле структури, але немає гарантії, що поля будуть розташовані безперервно.

1. Стек, реалізований за допомогою структури "Вузол", яка зберігає значення (в нашому прикладі типу int) і покажчик на наступний вузол. Це неефективна реалізація, яка вимагає видалення і виділення пам'яті під вузол при кожному виклику операції push і pop.

2. Реалізуємо структуру - масив, і деякі операції для роботи з масивами. Тип масиву задамо макропідстановки.

3. Структура Лінія, складається з двох структур точок. Для стислості реалізуємо тільки пару операцій

4. Структура комплексне число і функції для роботи з нею.

ru-Cyrl 18- tutorial Sypachev S.S. 1989-04-14 sypachev_s_s@mail.ru Stepan Sypachev students







Схожі статті