В языке Си определен еще один тип для размещения в памяти нескольких переменных разного типа. Это – объединение. Объявляется объединение так же, как и структура, например:
union u{
int i ;
char ch ;
long int l ;
};
Это объединение не задает какую-либо переменную. Оно задает шаблон объединения.
Можно объявить переменную:
union u alfa, beta ;
Можно было объявить переменные одновременно с заданием шаблона. В отличие от структуры для переменной типа union места в памяти выделяется ровно столько, сколько надо элементу объединения, имеющему наибольший размер в байтах. Так под переменную alfa будет выделено четыре байта, под переменную i – 2 байта; под переменную ch – 1 байт; под переменную l – 4 байта;
Синтаксис использования элементов объединения такой же, как и для структур:
u.ch = ‘ 5 ‘;
Для объединения разрешена также операция -->, если мы обращаемся к объединению с помощью указателя.
6.3. Битовые поля
Структура может содержать битовые поля. Целые компоненты типа signed и unsigned можно объявить битовыми полями шириной от 1 до 16 битов. Ширина битового поля и его необязательный идентификатор задаются следующим образом:
тип <идентификатор>: ширина;
где тип - это char, unsigned char, int или unsigned int .
Если идентификатор битового поля опущен, то число битов, заданное выражением ширина, распределяется в памяти, но поле при этом остается недоступным программе. Если при этом значение ширина равно нулю, то следующее поле будет начинаться со следующего слова памяти.
Пример:
struct str {
int i: 3;
unsigned j: 4;
int : 4
int k: 2;
} a ;
Для указанных в структуре полей задается следующее распределение памяти:
15 14 12 11 10 9 8 7 6 5 4 3 2 1 0
x x x x x x x x x x x x x x x
< -- > < -------- > < -------- > < ---- >
k не испол. j i
Целые поля хранятся в виде дополнения до 2, причем крайний левый бит является старшим. Для битового поля типа int (например, signed) старший бит интерпретируется как знаковый. Например, поле k типа signed int шириной 1 может содержать только значения –1 и 0, так как битовой шаблон 1 будет интерпретироваться как -1.
Пример 6.3:
#Include<stdio.h>
void main (void)
{
struct str {
int i:1;
unsigned j:4;
int l:4;
int k:2;
} a;
a.i=1;
printf(“%d”,a.i);
}
Результат работы программы: -1.
В отличие от других языков программирования язык Си обеспечивает доступ к одному или нескольким битам в байте или слове. Это имеет свои преимущества. Если многие переменные принимают только два значения, (такие переменные называют флагами), то можно использовать 1 бит.
Один из методов, встроенных в язык Си и позволяющих иметь доступ к биту, – это поля битов (bit-fields). В действительности поля битов – это специальный тип структуры, в котором определено, из каких бит состоит каждый элемент. Основная форма объявления такой структуры следующая:
struct имя_ структуры
{
тип имя 1: длина в битах ;
тип имя 2: длина в битах ;
…………………………. ;
тип имя N: длина в битах ;
}
В этом объявлении структур тип может быть одним из следующих: int, unsigned, signed. Имя I может быть пропущено, тогда соответственно число бит не используется (пропускается). Длина структуры всегда кратна восьми. Так, если указать:
struct onebit
{
unsigned one_bit : 1;
} obj ;
то для переменой obj будет выделено 8 бит, но использоваться будет только первый.
6.5. Переименование типов – typedef
Язык Си с помощью оператора typedef позволяет задавать новое имя уже существующим переменным. При этом не создается новый тип данных.
Например:
typedef char SIMBOL;
typedef unsigned UNSIGN;
typedef float real;
Достаточно часто используется оператор typedef с применением структур:
typedef struct st_tag {
char name[30];
int kurs;
char group[3];
int stip;
} STUDENT;
Теперь для определения переменной можно использовать