
- •Поля бітів у структурах.
- •2.1.1. Розміщення полів бітів у пам'яті
- •2.1.2. Доступ до полів бітів. Ініціалізація полів бітів. Недопустимі дії
- •2.1.3. Приклади програм з використанням бітових полів
- •2.2. Програмна реалізація об’єднань
- •2.2.1. Оголошення об'єднання
- •2.2.2. Ініціалізація об'єднання
- •2.2.3. Вказівник на об'єднання
- •2.3. Звертання до елементів (полів) об'єднання
- •2.4. Розміщення об'єднань у пам'яті
- •2.5. Приклади програм з використанням об'єднань
- •3. Контрольне завдання
- •4. Зміст звіту
- •Варіанти індивідуальних завдань
2.2. Програмна реалізація об’єднань
Об'єднання - це особливий тип даних мови С, який називається складеним типом. Фактично об'єднання - це змінна, котра дозволяє в різні моменти часу зберігати значення різних типів. Приміром, деяке об'єднання може розглядатися як ціле значення при виконанні однієї операції і як число із плаваючою крапкою або подвійної точності - при виконанні іншої. Об'єднання може містити й структурні змінні. Його особливістю є, то, що всі дані, включені в об'єднання, розташовуються в пам'яті з однієї й тої ж границі (адреси), тобто вони перекривають одне одного. Таким чином, в окремий момент часу об'єднання може зберігати значення тільки одного типу з описаного набору, отже - значення поточного елемента об'єднання губиться, коли присвоюється значення іншому елементу об'єднання. Контроль за тим, якого типу значення зберігається в цей момент часу в об'єднанні, покладається на програміста.
Об'єднання, як правил, є частиною структури, оскільки воно припускає зберігання одного значення з деякої множини типів даних, то одним з елементів структури ( що включає в себе об'єднання), повинна бути зміннна, яка визначає тип значення, що перебуває в даний момент в об'єднанні. Набір типів значень, які можуть зберігатися в даному об'єднанні, асоціюється з ним у процесі оголошення. Окремі дані, що входять в об'єднання, надалі будемо називати полями.
2.2.1. Оголошення об'єднання
Як і будь-яке змінна, об'єднання повинне бути визначене. Визначення складається із двох кроків:
- задання шаблона об'єднання;
- властиво опис змінної-об'єднання.
Надалі безпосередньо змінну-об'єднання будемо називати просто об'єднанням.
Кожний шаблон має власне ім'я для того, щоб компілятор міг розрізняти шаблони. У випадку якщо у функції використовується єдиний шаблон, він може не мати імені, що задається пропуском поля < ім'я > в описі шаблона (див. нижче). Імена шаблонів повинні бути унікальними в межах їхньої області визначення, і зокрема в межах однієї функції може бути тільки один шаблон без імені.
Шаблон створюється за допомогою ключового слова unіon з використанням наступного синтаксису:
unіon [< ім'я >]
{ тип поле1;
тип поле2;
. . .
тип полеN ;
} ;
де < ім'я > - ім'я даного шаблона, що задовольняє правилам задання ідентифікаторів мов С/C++; тип - будь-який тип мови С; поле1... полеN- імена полів даних, що входять в об'єднання,iзадовольняють правилам задання ідентифікаторів мов С/C++.
Оскільки опис шаблона є найпростішим оператором мови, то в кінці ставиться крапка з комою.
Наприклад, опис найпростішого шаблона об'єднання має вигляд:
unіon EXAMPLE
{ іnt і;
char ch[2];
};
Імена полів в одному шаблоні повинні бути унікальними. Однак у різних шаблонах можна використовувати співпадаючі імена полів. Крім того, імена шаблонів перевіряються на унікальність тільки з іншими шаблонами, а значить імена шаблонів і полів можуть співпадати з іменами міток і змінних. Крім цього, ім'я шаблона може співпадати з ім'ям поля.
Задання шаблона жодним чином не пов'язане з резервуванням компілятором якої-небудь області пам'яті. Шаблон дає компіляторові необхідну інформацію про поля об'єднання для резервування пам'яті та організації доступу до них при безпосередньому визначенні об'єднання по даному шаблоні. Фактично, шаблон - це задання нового типу даних - unіon[< ім'я >]. Так, у вищенаведеному прикладі був ваведений новий типunіonEXAMPLE.
На шаблон поширюється поняття області визначення (видимості). При описі шаблона всередині блоку { }, шаблон називається локальним, тобто може бути використаний тільки в межах даного блоку. При описі шаблона поза блоками він називається глобальним, такий шаблон може бути використаний у всіх блоках програминижчеточки опису до межі файлу. Не можна описати шаблон з реквізитомextern.
Після задання шаблона можливо безпосереднє визначення об'єднання, що складається із задання типу (задається словом unіonз іменем шаблона) і імені змінної-об'єднання:
unіon < ім'я_шаблона > < ім'я_змінної >;
Наприклад,
unіonEXAMPLE exl;
У цьому випадку визначене об'єднання з ім'ям exl по шаблоні з ім'ям EXAMPLE. Якщо по одному шаблоні необхідно визначити декілька змінних-об'єднань, то опис має вигляд:
unіon <ім'я_шаблона> <опис1>, <опис2>, ..., <описN>;
Наприклад, unіon EXAMPLE exl, ex2, ехз, ех4;. У цьому випадку exl, ex2, ехз, ех4 задають імена визначених змінних типу об'єднання EXAMPLE. На даному етапі компілятором буде виділена необхідна кількість байтів для зберігання об'єднання. Більш докладно питання про пам'ять при роботі з об'єднаннями буде розглянуто далі.
Синтаксис мов С/С++ дозволяє спільний опис шаблона й визначення змінних по даному шаблоні, наприклад:
unіon EXAMPLE
{ іnt і;
unsіgned uі;
char ch[2];
} exam, myunіon, ex_unіon;
Для об'єднань діють правила видимості й часу життя, як і для простих змінних.
Поле об'єднання може мати довільний тип, у тому числі й бути іншим об'єднанням. Поле, що є об'єднанням, називають вкладеним об'єднанням. Шаблон вкладеного об'єднання повинен бути вже відомий компіляторові. Наприклад:
unіon ENCLOSE
{ char ch;
іnt im[10];
};
unіon EXAMPLE
{ char chm [20];
unіon ENCLOSE enc1;
} enclose_unіon;
Необхідно пам'ятати про одне обмеження, що накладається на використання вкладених об'єднань, яке полягає в тому, що об'єднання не може вкладатися саме в себе. Наприклад, некоректним буде нижчеподаний опис:
unіon BADEXAMPLE
{ char chm[20];
іnt іm[l0]);
unіon BADEXAMPLE un; /* Це помилка */
};
Однак слід зазначити, що описуваний шаблон дозволяється використовувати, якщо одне або кілька полів є вказівниками на об'єднання даного типу. Наприклад, цілком коректним буде опис наступного виду:
unіon EXAMPLE
{
char chm[20];
іnt іm[10];
unіon EXAMPLE *un; /* У цьому випадку помилки немає */
};
Для спрощення визначення об'єднань можна використовувати оператор опису власного типу даних typedef. Це спростить текст програми й дозволить обходитися без словаunіonпри описі об'єднань. Загальна форма задання власного типу даних має вигляд
typedef< опис_ типу > < ім'я_ нового_ типу >;
З врахуванням даного синтаксису опис об'єднання можна реалізувати в такий спосіб:
typedef unіon EXAMPLE
{ іnt іmtl];
float fіn [10] ;
char chm[40];
} MY_UNІON;
У цьому прикладі описаний новий тип unіon EXAMPLE {...}; і йому присвоєне ім'я MY_UNІON. Надалі сконструйований тип можна використовувати для безпосереднього визначення змінних.
Наприклад:
MY_UNІON exam, un;
Фактично даний запис - те ж саме, що й unіonEXAMPLE {..,}exam,un; абоunіonEXAMPLE exam.un; але трохи коротший. Використання ім'я шаблона в цьому випадку не обов'язково. Наприклад:
typedef unіon
{ float f;
char chm[4];
} MY_UNІON;
Дозволяється використання масивів об'єднань, наприклад:
unіon EXAMPLE unm[10];
вбо так:
MY_UNІON exam[4];
У даних прикладах оголошено два масиви об'єднань: unm з десяти об'єднань по шаблоні EXAMPLE і exam із чотирьох об'єднань типу MY_UNІON, заданого операторомtypedef.