Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Структуры в С++.doc
Скачиваний:
3
Добавлен:
14.11.2019
Размер:
109.06 Кб
Скачать

9.3. Объединения

Объединения – это такие наборы данных, которые компилятор должен разместить в оперативной памяти, начиная с одного и того же места. Впервые такое совмещение разных данных появилось в языке ФОРТРАН, где для этой цели использовался оператор EQUIVALENCE (эквивалентность). Основным назначением этого оператора была попытка экономии оперативной памяти за счет размещения вновь используемых массивов на месте уже отработавших массивов. В последующем этот оператор использовался и для совместного доступа к одним и тем же полям оперативной памяти как к данным разного типа. Наконец, еще одна дополнительная услуга со стороны оператора EQUIVALENCE состояла в том, что программисты, создающие разные фрагменты программы могли использовать разные имена для обозначения одних и тех же физических величин. Эквивалентность двух разных имен позволяла свести к минимуму переделки при объединении фрагментов программ.

В языках C, C++ объединения создаются с помощью оператора union. В рамках MS-DOS, где нехватка оперативной памяти давала себя знать, с помощью объединений можно наложить друг на друга массивы, используемые в разное время. Однако наиболее важная цель объединений – расположить в одном и том же месте данные разного типа. Это позволяет обращаться к тем или иным полям, используя переменные разного типа. Наиболее характерным объектом такого типа является ячейка электронной таблицы, в которой пользователь может разместить текст или числовое выражение того или иного типа.

Самым употребительным объединением в рамках MS-DOS было использование машинных регистров при обращении к функциям BIOS и операционной системы. Для этой цели в заголовочном файле dos.h было определено объединение REGS:

struct WORDREGS // структура из 16-битных данных

{ unsigned int ax,bx,cx,dx,si,di,cflag,flags; };

struct BYTEREGS // структура из 8-битных данных

{ unsigned char al,ah,bl,bh,cl,ch,dl,dh; }

union REGS {struct WORDREGS x;

struct BYTEREGS h; };

В этих объявлениях содержатся описания двух структур, которые имитируют распределение в оперативной памяти машинных регистров процессора Intel-8086. На языке ассемблера эти регистры обозначаются как 16-битные регистры общего назначения (AX, BX, CX, DX), индексные регистры (SI, DI) и регистры флагов (CFLAG, FLAGS). Особенность регистров общего назначения в том, что каждый из них объединяет по 2 байта, к которым возможен автономный доступ – отдельно к старшему байту регистра (AH, BH, CH, DH), отдельно к младшему байту (AL, BL, CL, DL). При обращениях к функциям MS-DOS приходится оперировать и с каждым байтом того или иного регистра, и с общим содержимым обоих байтов. Например, функция перевода курсора дисплея в заданную позицию, реализуется следующим фрагментом программы на языке ассемблера:

MOV AH,2 ; номер функции 2 засылается в регистр AH

MOV BH,0 ; номер страницы в текстовом режиме

MOV DH,10 ; номер строки, в которую переводится курсор

MOV DL,25 ; номер колонки

INT 10H ; вызов прерывания с номером 16

Для того чтобы выполнить аналогичные действия (не прибегая к библиотечной функции gotoxy) на языке C надо проделать следующие операции:

union REGS r; //заводим область регистров в памяти

...............

r.h.ah=2; //засылаем номер функции в "регистр" AH

r.h.bh=0; //засылаем номер страницы в "регистр" BH

r.h.dh=y; //засылаем номер строки в "регистр" DH

r.h.dl=x; //засылаем номер столбца в "регистр" DL

int86(0x10,&r,&r); //имитация прерывания с номером 10h

Функция int86 перепишет содержимое объединения r в машинные регистры, предварительно сохранив их содержимое, выполнит команду прерывания, передающую управление подфункции MS-DOS с номером 2, которая переместит курсор в заданную позицию. По окончании работы подфункции содержимое машинных регистров запомнится в объединении r, а их прежнее содержимое будет восстановлено.

Может быть, вам покажется, что приведенный фрагмент излишне усложнен, но реальная работа функции gotoxy(x,y) требует еще большего числа операций.

В языке C++ также была предпринята попытка использовать объединения для создания классов. Однако о деталях другого использования объединений в разделе "C++ и объектно-ориентированное программирование".