Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lekcija-18.pdf
Скачиваний:
17
Добавлен:
27.03.2016
Размер:
285.74 Кб
Скачать

for (i=0; md->d > dofm[v][i]; i++)

//пересчет порядкового значения дня года

md->d -=dofm[v][i];

//в день месяца

md->m=i;

//присваивание значения месяцу

}

Объединение как пользовательский тип и совокупность данных

Определение объединения и переменной объединяющего типа

Объединения находятся в близком родстве со структурами. Объединением будем называть переменную, созданную, как и в случае структур, по шаблону. Определяются объединения (шаблоны объединения, объединяющие типы) с помощью служебного слова union. Объединения, подобно структурам, содержат поля различных типов, но только размещаются эти поля в одно и то же место памяти (начинаются с одной границы). Основное назначение объединения – обеспечить возможность доступа к одному и тому же участку памяти с помощью объектов разных типов.

Определим переменную UNI объединяющего типа с помощью анонимного шаблона: union {

long L; unsigned i1; int i2;

char c[4];

} UNI;

Схема размещения переменной UNI в памяти: long L

unsigned i1 int i2

char c[4]

т.е. элементы располагаются с одного адреса. Это подтвердит и выполнение следующих операторов:

cout << &UNI.L; //все переменные имеют один и тот же адрес cout << &UNI.i1;

cout << &UNI.i2; cout << &UNI.c;

Размер памяти, выделяемый объединению, равен максимальному из размеров памяти, выделяемых для отдельных полей шаблона. Тип поля может быть любым, в том числе и структурой. Структуры могут быть членами объединения, и объединение может быть членом структуры. Разрешается создание и массива объединений.

Переменные типа объединение могут быть формальными параметрами и аргументами вызова функций. Чтобы функция не изменила аргумент-объединение при передаче по указателю или ссылке, соответствующий параметр объявляется со спецификатором const. Функция может возвращать переменную-указатель или ссылку типа объединение.

Доступ к полям объединения выполняется, аналогично структурам, через уточненное

имя:

имя_объединения.имя_поля

Программирование – лекция 18 (лекции Стрикелевой Л.В.)

15

(*указатель_на_объединение).имя_поля указатель_на_объединение->имя_поля

ссылка_на_объединение.имя_поля

Внимание!!! Члены-данные анонимного объединения можно использовать как переменные (если их имена уникальны в контексте объявления). Например:

enum

week {sun, mon, tues, weds, thurs, fri, sat};

union {

// анонимное объединение

 

int i;

 

};

week w;

 

 

 

i = 6;

if ((w == sun) || (w == sat))

cout << “Это выходные дни!”;

Объединения могут быть опасны, так как их реализация часто зависит от системы.

Если бы элементы объединения имели одинаковую длину и одинаковый тип, а отличались только именами, то использование объединения было бы подобно применению ссылок: один участок памяти имел бы несколько различных имен.

Заносить значения в участок памяти, выделенный для объединения, можно с помощью любого из элементов:

union {

int ival; float fval; char cval[4];

} uval;

Переменной uval можно присваивать любой из трех типов; какой тип в данный момент находится в переменной – должен помнить программист.

Но:

инициализироваться объединение может только первым описанным полем.

Инициализатор объединения – значение для его первого члена, заключенное в фигурные скобки. Например:

union int_flt {

 

 

int i;

 

 

float x;

 

} n = {0};

// член (поле) i инициализируется нулем.

n.i = 7;

 

//в объединение записано целое значение

cout << n.i

<< endl;

// объединение интерпретируется как имеющее целый тип

n.x = 7.0;

 

// в объединение записано вещественное значение

cout << n.x

<< endl;

//объединение интерпретируется как имеющее вещественный тип

Основное достоинство объединений – возможность разных трактовок одного и того же содержимого памяти.

Пусть имеем объединение: union

{float f; unsigned long k;

Программирование – лекция 18 (лекции Стрикелевой Л.В.)

16

} FK;

 

 

Можно присвоить объединению

вещественное

значение FK.f = -256.5, а

рассматривать его затем как беззнаковое целое:

 

cout << hex << FK.k;

//получим с3804000 16.

Если же включить в шаблон объединения массив: union

{double f; char h[8];

}FLH;

ивыполнить присваивание вещественного значения переменной FLH присваиванием этого значения полю FLH.f, то имеем возможность доступа к отдельным байтам

внутреннего представления этого значения с помощью имен FLH.h[0], FLH.h[1], и т.д.

Примеры использования объединений Получение внутреннего представления вещественного числа

union bits{

double d;

unsigned char c [sizeof (double)];

};

int main ()

{

bits ob={199.5};

for (int j=sizeof(double)-1; j>=0; j--)

{

cout << "byte " <<j << ":

";

 

for (int i=128; i; i>>=1)

cout << "1";

 

if (i & ob.c[j])

 

else cout << "0";

 

 

cout << "\n";

 

 

}

 

 

_getch();

 

 

return 0;

 

 

}

 

 

Например, внутреннее представление числа -256.5:

С0 70 08 00 00 00 00 00 16

в памяти значение хранится в виде:

 

00 00 00 00 00 08 70 С016

Объяснение, как получено это значение, дано в разделе «Внутреннее представление вещественных чисел» лекции 7.

Использование перечисляемого типа для обращения к полям объединения

int main()

{ enum paytype {CARD, CHECK}; //две формы оплаты с числовыми значениями 0, 1 paytype ptype; //определение переменной перечисляемого типа union

{char card[25]; long check;

} info;

Программирование – лекция 18 (лекции Стрикелевой Л.В.)

17

Возможное присваивание значения объединению:

ptype = CARD; //переменная-флаг получает значение CARD (0) strcpy(info.card, "12345"); //объединение получает свое значение через поле card

или

ptype = paytype(1); //переменная–флаг получает значение CHECK (1) info.check= 105l; //объединение получает свое значение через поле check

Вывод значения переменной на экран: switch (ptype) {

case CARD: cout <<"card:" << info.card<< endl; break;

case CHECK: cout <<"check:" << info.check<< endl; break;

}

_getch(); return 0;

}

Реализуем пример по-другому.

Создадим структуру, включающую объединение и поле перечисляемого типа, характеризующее форму оплаты:

int main()

{

enum paytype {CARD, CHECK}; //две формы оплаты struct{

paytype ptype; //поле-флаг включено в состав структуры union

{char card[25]; long check;

} info;

} str;

Возможное присваивание значения объединению:

str.ptype = paytype(0); //заполняем поле-флаг объединения, как элемента структуры strcpy(str.info.card, "12345");//объединение, как элемент структуры,

//получает свое значение через поле card

или

str.ptype = paytype(1); //заполняем поле-флаг объединения, как элемента структуры str.info.check= 105l; //объединение, как элемент структуры,

//получает свое значение через поле check

Вывод на экран значения объединения как элемента переменной-структуры:

switch (str.ptype) {

case CARD: cout <<"card:" << str.info.card<< endl; break; case CHECK: cout <<"check:" << str.info.check<< endl; break;

}

_getch(); return 0;

}

Программирование – лекция 18 (лекции Стрикелевой Л.В.)

18

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]