Структури та об'єднання

Структури. Синтаксично структури задаються так:

struct[<тег>]{<список оголошення елементів>}<описувач>

Інша форма

struct<тег><описувач>[…<описувач>]

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

struct point {int x,

int y;} A,B;

struct {int x; float y;} Z,S;

Доступ до елемента структури здійснюється у два способи. Якщо визначено екземпляр структури, то доступ здійснюється конструкцією вигляду <описувач>.<ім’я поля>. У випадку, коли оголошено покажчик на екземпляр структури, доступ здійснюється з використанням операції ->:

<покажчик>-><ім’я поля>

struct point *pa;

pa->x=4;

Структури можуть бути вкладеними, тобто полем структури також може бути структура:

struct line {int d;

struct point a;

struct point b;}

L1,L2;

Доступ здійснюється так:

L1.a.x=2;

L2.b.y=3;

Використовуємо стільки операцій доступу, скільки є рівнів вкладеної структури. Якщо оголосити покажчик на структуру line

struct line *pl;

то доступ здійснюється так:

(pl->a).x=4;

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

struct point k[6];

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

<поле>:<константа>

Наприклад:

struct bit{

int i:1;

int p:5;

int l:3;

};

Тоді поле i займатиме 1, р – 5, l – 3 біти.

Об'єднання. Синтаксично об'єднання задаються аналогічно структурам:

union[<тег>]{<список оголошення елементів>}<описувач>

union<тег><описувач>[…<описувач>]

Наприклад:

Union u_tag

{

int ival;

float fval;

char *pval;

} uval;

Об'єднання мають деякі спільні властивості зі структурами: однаковий механізм доступу до полів, можна задавати бітові поля тощо. Специфіка об'єднання полягає в тому, що всі поля мають однакову адресу в пам'яті (однаковий зсув). Присвоєння значення якомусь полю приведе до втрати інформації, що зберігалася в іншому до цього присвоєння. У різні моменти часу об’єднання може містити об'єкти різних типів і розмірів. Це і є його основним призначенням. У наведеному фрагменті програми змінна uval матиме достатній розмір, щоб зберігати найбільший із трьох типів незалежно від машини, на якій здійснюється компіляція – програма не буде залежати від характеристик апаратних засобів. Будь-яка змінна із цих трьох типів може бути присвоєна uvar і потім використана у виразах. Справа програміста – стежити за тим, який тип зберігається в об'єднанні в даний момент. Синтаксично доступ до членів об'єднання здійснюється аналогічноструктурам:Ім’яОб’єднання. Ім’яЧлена

чи

ПокажчикОб’єднання -> Ім’яЧлена

Якщо для відстеження типу, збереженого в даний момент в uval, використовується змінна utype, то можна написати такий фрагмент програми:

if (utype==int)

printf("%d\n", uval.ival);

else if (utype==float)

printf("%f\n", uval.fval);

else if (utype==string)

printf("%s\n", uval.pval);

Else

printf("bad type %d in utype\n", utype);

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

struct {

char *name;

int flags;

int utype;

union {

int ival;

float fval;

char *pval;

} uval;

} symtab[nsym];

на змінну ival можна посилатися так:

symtab[i].uval.ival

а на перший символ рядка pval так:

*symtab[i].uval.pval

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: