- •Массивы структур
- •Структуры – параметры функций
- •Если обработка структуры в функции связана с изменением содержимого полей, то такую структуру необходимо передавать по указателю или по ссылке. Доступ к отдельному биту
- •Структуры
- •9.1.1. Объявление и инициализация структур
- •Структуры – параметры функций
- •9.1.3.Функции, возвращающие структуры
- •9.2. Перечисления
- •9.3. Объединения
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++ и объектно-ориентированное программирование".