Об’єднання. Ключове слово union. Приклади використання об’єднань
Зміст
- Питання/відповідь
- 1. Що таке об’єднання в мові C++? Для чого використовуються об’єднання?
- 2. Як виглядає загальна форма оголошення типу (шаблону) об’єднання? Ключове слово union
- 3. Що таке довжина об’єднання? Як обчислюється довжина об’єднання?
- 4. Як оголосити тип (шаблон) об’єднання та змінну цього типу? Приклад
- 5. Як здійснюється доступ до полів об’єднання?
- 6. Приклад оголошення та використання покажчика (*) на об’єднання
- 7. Як оголосити вкладені об’єднання (структури, класи) в шаблоні об’єднання? Приклад
- 8. Як описати масив об’єднань? Приклад
- 9. Які особливості застосування операції sizeof() для об’єднань та структур?
- Зв’язані теми
Пошук на інших ресурсах:
1. Що таке об’єднання в мові C++? Для чого використовуються об’єднання?
Об’єднання – це групування змінних, які розділяють одну й ту ж область пам’яті. В залежності від інтерпретації здійснюється звертання до тієї чи іншої змінної об’єднання. Усі змінні, що включені в об’єднання починаються з однієї границі.
Об’єднання дозволяє представити дані, що змінюються в компактному вигляді. Одні й ті ж дані можуть бути представлені різними способами з допомогою об’єднань.
Так як і структури, об’єднання вимагають оголошення типу (шаблону) та оголошення змінної цього типу.
2. Як виглядає загальна форма оголошення типу (шаблону) об’єднання? Ключове слово union
Оголошення об’єднання (типу об’єднання або шаблону об’єднання) починається з ключового слова union.
union ім’я_типу_об’єднання { тип змінна1; тип змінна2; ... тип зміннаN; };
де
- ім’я_типу_об’єднання – безпосередньо ім’я новостворюваного типу;
- змінна1, змінна2, зміннаN – змінні, що є полями об’єднання. Ці змінні можуть бути різних типів;
- тип – тип змінної, що є полем об’єднання.
Тип змінної може бути:
- базовим типом, прийнятим в мові C++/CLI;
- тип структура;
- тип об’єднання;
- тип клас.
3. Що таке довжина об’єднання? Як обчислюється довжина об’єднання?
Довжина об’єднання – це розмір пам’яті в байтах, що виділяється для однієї змінної цього типу об’єднання.
Довжина об’єднання обчислюється як максимум з усіх довжин (розмірів у байтах) окремих полів шаблону. Слід нагадати, що одне поле – це оголошення однієї змінної в об’єднанні (див. п. 2).
4. Як оголосити тип (шаблон) об’єднання та змінну цього типу? Приклад
Нехай задано тип об’єднання, що містить змінні типів з плаваючою точкою
// оголошення типу "об'єднання Floats" union Floats { float f; // розглядається 4 байти double d; // розглядається 8 байт };
Тип об’єднання Floats містить 2 змінні з іменами f та d. Змінна f є типу float, змінна d є типу double. Для змінної f типу float розглядається (береться до уваги) 4 байти. Для змінної d типу double береться до уваги 8 байт, тому що компілятор виділяє для цього типу саме 8 байт.
Щоб використати об’єднання Floats в іншому програмному коді (методі, обробнику події тощо) потрібно оголосити змінну типу Floats як показано нижче
Floats Fl; int d; Fl.f = 20.5; // Fl.d не визначене Fl.d = -100.35; // тепер Fl.f не визначене d = sizeof(Fl); // d = 8
Оскільки розміщення змінних в пам’яті умовно починається з однієї адреси, то для змінної Fl типу Floats виділяється 8 байт пам’яті. Це зв’язано з тим, що змінна типу double вимагає більше пам’яті для свого представлення ніж змінна типу float.
На рисунку 1 відображено розміщення (інтерпретація) змінних f, d з об’єднання Floats.
Рис. 1. Представлення змінних f, d в об’єднанні Floats
5. Як здійснюється доступ до полів об’єднання?
Доступ до полів об’єднання здійснюється так само, як і для структури:
- з допомогою символу ‘ . ‘;
- з допомогою послідовності символів ‘->’ у випадку, коли оголошено змінну-покажчик на об’єднання.
6. Приклад оголошення та використання покажчика на об’єднання
Робота об’єднань з некерованими (*) покажчиками є така сама, як і робота структур з некерованими покажчиками.
У нижченаведеному прикладі оголошується некерований покажчик на об’єднання типу Ints
Демонстрація використання некерованого покажчика (*) для об’єднання типу Ints
// покажчик на об'єднання Ints *pI; // некерований покажчик // виділити пам'ять для об'єднання pI = new Ints; // доступ до полів з допомогою покажчика pI->a = 200; pI->b = 3400;
7. Як оголосити вкладені об’єднання (структури, класи) в шаблоні об’єднання? Приклад
Шаблон об’єднання може включати поля, що є структурами, об’єднаннями та класами.
У прикладі нижче оголошується шаблон об’єднання з іменем Types, що містить два вкладені об’єднання Floats та Ints, структуру ArrayOfChars і клас MyPoint.
Оголошення структури та об’єднань має такий вигляд
// об'єднання цілочисельних типів union Ints { unsigned short int a; unsigned int b; unsigned long int c; }; // структура, що містить 2 рядки struct ArrayOfChars { char A[10]; char B[8]; }; // оголошення типу "об'єднання Floats" union Floats { float f; // розглядається 4 байти double d; // розглядається 8 байт };
Оголошення шаблону класу має такий вигляд:
// клас оголошується в окремому модулі, наприклад MyPoint.h #pragma once class MyPoint { public: int x; int y; // методи класу int GetX(void) { return x; } int GetY(void) { return y; } void SetXY(int nx, int ny) { x = nx; y = ny; } };
Оголошення типу об’єднання Types з вкладеними складними типами Ints, Floats, ArrayOfChars, MyPoint.
// підключити модуль з оголошеним класом MyPoint #include "MyPoint.h" ... // оголошення типу "об'єднання Types" union Types { Floats Fl; // об'єднання Ints I; // об'єднання ArrayOfChars A; // структура MyPoint MP; // клас };
Використання об’єднання Types в деякому програмному коді:
// оголосити змінну типу "об'єднання Types" Types T; // змінити значення полів змінної T T.Fl.f = (float)20.35; // об'єднання Floats T.I.b = 230; // об'єднання Ints T.A.A[2] = 'A'; // структура ArrayOfChars T.MP.SetXY(3,8); // клас MyPoint int d; d = T.MP.GetX(); // d = 3
8. Як описати масив об’єднань? Приклад
// Приклад оголошення та використання масиву об'єднань Floats F[5]; // оголошується масив з 5 об'єднань типу Floats // заповнення значень полів for (int i=0; i<5; i++) { F[i].d = i*0.2 + i*i; }
9. Які особливості застосування операції sizeof() для об’єднань та структур?
У програмах на C++ для визначення розміру змінної типу “структура” або “об’єднання” обов’язково потрібно використовувати операцію sizeof. Визначення розміру “вручну” є помилковим тому що:
- розміри деяких вбудованих типів (наприклад тип int) можуть бути різними для різних комп’ютерів. Наприклад, на одних платформах для типу int буде виділено 2 байти, на інших 4 байти;
- компілятор робить так зване “вирівнювання пам’яті” на межі слова (2 байти) або абзацу (16 байт). Наприклад, якщо компілятор робить вирівнювання на межі абзацу, то структура (об’єднання) типу ArraysOfChars:
// структура, що містить 2 рядки struct ArrayOfChars { char A[10]; char B[8]; };
може займати в пам’яті 24 байти. Тому що для масиву A виділяється 16 байт а не 10 байт. Компілятор додатково виділяє 6 байт щоб реалізувати вирівнювання на межі абзацу.
Таким чином, використання операції sizeof() для визначення типу структури чи об’єднання гарантує переносність програмного коду.
Зв’язані теми
- Структури. Складені типи даних. Шаблон структури. Структурна змінна. Структури в середовищі CLR. Оголошення та ініціалізація структурної змінної
- Масиви. Визначення масиву. Одновимірні масиви. Ініціалізація масиву