Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КТіП Лекції 20110516 (1).doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1 Мб
Скачать
☆
    1. Перейменування типів

До складу мови С++ входить спеціальна декларація typedef, яка дає програмісту змогу надавати власні імена типам даних програми. Синтаксис перейменування типів такий:

typedef тип користувацьке_ім’я_типу;

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

typedef unsigned int UINT;

UINT a = 23, b;

В цьому прикладі ми перейменували тип даних unsigned int в UINT. Після цього нове ім’я (UINT) можна використовувати в програмі так само, як і старе (unsigned int).

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

typedef char STRING[ 80 ];

STRING s = "a string";

cout << s << endl;

Використання декларації typedef сприяє підвищенню наочності імен типів даних та скорочує їх запис. Це передусім стосується таких типів даних, як структури, об’єднання і переліки, для яких typedef можна використовувати одночасно з оголошенням шаблону. Наприклад:

typedef struct student {

char name[ 40 ];

int number;

int rating;

} STUDENT;

STUDENT s = { "James Bond", 12, 80 };

Крім наочності та простоти іменування типів декларація typedef дає програмістові змогу створювати машино незалежні типи даних. Насамперед це стосується тих типів, параметри яких залежать від апаратних особливостей комп’ютера. Якщо такому типові надати певне typedef – ім’я і використовувати це ім’я всюди в тексті програми, то в новому середовищі достатньо внести зміни в рядок декларації typedef, щоб встановити нові параметри для перейменованого типу.

    1. Об’єднання

Об’єднання – це особливий тип даних, який дає змогу записувати в одну і ту ж встановлену ділянку оперативної пам'яті дані різних типів і розмірів. Таким чином створюється ділянка пам'яті спільного користування, до якої можна звертатись рідними способами через одну змінну, що має тип об’єднання.

Оголошення об’єднання подібне до оголошення структури: задається шаблон об’єднання і перелічуються відповідні змінні. Так само, як і для структур, шаблон об’єднання можна оголошувати окремо або одночасно з оголошенням змінних. У разі автономного оголошення шаблону об’єднання застосовують синтаксичну конструкцію, аналогічну до шаблону структури, але починають її ключовим словом union:

union тег_ об’єднання {

тип_поля_1 ім’я_поля_1;

тип_поля_2 ім’я_поля_2;

тип_поля_3 ім’я_поля_3;

…

};

Тег об’єднання ідентифікує дане об’єднання, а список полів задає перелік даних, які можна заносити в це об’єднання.

Як і у випадку структур, змінні з типом об’єднання можна оголошувати спільно з оголошенням шаблону або пізніше, використовуючи тип union тег об’єднання. Обсяг ділянки пам'яті, яка виділяється для кожної змінної, що має тип об’єднання, визначається розміром найдовшого поля даного об’єднання.

#include <iostream>

using namespace std;

int main() {

union demo {

double d;

int i;

char c;

};

union demo d;

d.d = 1.2;

cout << d.d << endl; // 1.2

cout << d.i << endl; // 858993459

cout << d.c << endl; // 3

}

Всі три ділянки змінної d займають спільну ділянку оперативної пам'яті, обсяг якої буде дорівнювати розміру найдовшого поля. Якщо розмір змінних типів double, int i char складає 8, 4 і 1 байт відповідно, то розмір змінних типу union demo буде 8 байт. Всі три ділянки мають однакове нульове зміщення відносно адреси початку ділянки, яку займає змінна.

При оголошенні змінних з типом об’єднання можна виконувати ініціалізацію. Але ініціалізувати об’єднання можна значенням, сумісним з типом першого поля цього об’єднання. Наприклад:

#include <iostream>

using namespace std;

int main() {

typedef union demo {

double d;

int i;

char c;

} TEST;

TEST d = { 2.3 };

cout << d.d << endl;

}

До змінних з типом об’єднання можна застосовувати всі операції, що й до структурних змінних: присвоювання (тобто копіювання цілого об’єднання), визначення адреси змінної, виділення окремих елементів (полів) об’єднання. Для звертання до полів об’єднання використовують такі ж синтаксичні конструкції на основі операцій «крапка» і «стрілка», як і в разі звертання до елементів структур:

ім’я_змінної_об’єднання.ім’я_поля

вказівник_на_об’єднання->ім’я_поля

Поля об’єднань можуть бути довільного типу – простого чи складеного. Зокрема, поле об’єднання може бути структурою, вкладеним об’єднанням або вказівником на структуру чи об’єднання. Водночас об’єднання можуть бути елементами масиву або складовими частинами структур інших типів.

В якості приклада розглянемо таку програму. Необхідно зберігати інформацію про платіж, який може здійснюватися кредитною карткою або чеком. Для збереження інформації про платіж кредитною карткою необхідний масив символів з 25 елементів, для збереження інформації про платіж чеком – довге ціле. Двома методами одночасно платіж здійснений не може бути, тому можна використовувати об’єднання:

union payment {

char card[ 25 ];

long check;

};

В кожен момент часу в змінній типу об’єднання зберігається тільки одне значення, відповідальність за його правильне використання лежить на програмісті. Тому зручно разом з об’єднаннями зберігати інформацію про те, який саме елемент використовується в даний момент.

#include <iostream>

using namespace std;

int main() {

enum paytype { CARD, CHECK };

struct payment {

paytype ptype;

union {

char card[ 25 ];

long check;

};

};

payment p;

p.ptype = CHECK;

p.check = 123456;

switch ( p.ptype ) {

case CARD: cout << p.card << endl; break;

case CHECK: cout << p.check << endl; break;

}

}

В цьому прикладі використовується об’єднання без імені, тому для звертання до його полів необхідно просто вказувати імена цих полів.