Опция <tag>- это идентификатор, который именует тип перечисления, определенного в <enum-list>.
Переменную перечисления именует <identifier>. В объявлении может быть описана более чем одна переменная перечисления.
Во второй форме используется тег перечисления, который ссылается на тип перечисления. В этой форме объявления список перечисления не представлен, поскольку тип перечисления определен в другом месте. Если задаваемый тег не ссылается на уже определенный тип перечисления, или если именуемый тегом тип находится вне текущей видимости, то выдается ошибка.
<enum-list> имеет следующий синтаксис:
<identifier>[=<constant-expression>][,<identifier>
[=<constant-expression]]...
Каждый идентификатор именует элементы перечисления. По умолчанию первому идентификатору соответствует значение 0, следующий идентификатор ассоциируется со значением 1 и т. д. Имя константы перечисления эквивалентно ее значению.
Запись =<constant-expression> переопределяет последовательность значений, заданных по умолчанию. Идентификатор, следующий перед записью =<constant-expression> принимает значение, задаваемое этим константным выражением. Константное выражение имеет тип int и может быть отрицательным. Следующий идентификатор в списке ассоциируется с величиной, равной <constant-expression>+1, если он явно не задается другой величиной.
Перечисление может содержать повторяющиеся значения идентификаторов, но каждый идентификатор должен быть уникальным. Кроме того, он должен быть отличным от всех других идентификаторов перечислений с той же видимостью. Например, двум различным идентификаторам null и zero может быть задано значение 0 в одном и том же перечислении. Идентификаторы должны быть отличны от других идентификаторов с той же самой видимостью, включая имена обычных переменных и идентификаторы других перечислений. Теги перечислений должны быть отличны от тегов перечислений, тегов структур и совмещений с той же самой видимостью.
Примеры:
/**************** Example 1 ***************/
enum day {
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday;
/***************** Example 2 ***************/
enum day today = wednesday;
В первом примере определяется тип перечисления, поименованный day и объявляется переменная workday этого типа перечисления. С saturday по умолчанию ассоциируется значение 0. Идентификатор sunday явно устанавливается в 0. Оставшиеся идентификаторы по умолчанию принимают значение от 1 до 5.
Во втором примере переменной today типа enum day присваивается значение из перечисления. Заметим, что для присваивания используется имя константы из перечисления. Так как тип перечисления day был предварительно объявлен, то достаточно сослаться только на тег перечисления.
Синтаксис: struct[<tag>]{<member-declaration-list>}<declarator>[,<declarator>...]; struct<tag><declarator>[,<declarator>...];
Объявление структуры задает имя типа структуры и специфицирует последовательность переменных величин, называемых элементами структуры, которые могут иметь различные типы.
Объявление структуры начинается с ключевого слова struct и имеет две формы представления, как показано выше. В первой форме представления типы и имена элементов структуры специфицируются в списке объявлений элементов <member-declaration-list>. <tag>- это идентификатор, который именует тип структуры, определенный в списке объявлений элементов.
Каждый <declarator> задает имя переменной типа структуры. Тип переменной в деклараторе может быть модифицирован на указатель к структуре, на массив структур или на функцию, возвращающую структуру.
Вторая синтаксическая форма использует тег- <tag> структуры для ссылки на тип структуры. В этой форме объявления отсутствует список объявлений элементов, поскольку тип структуры определен в другом месте. Определение типа структуры должно быть видимым для тега, который используется в объявлении и определение должно предшествовать объявлению через тег, если тег не используется для объявления указателя или структурного типа typedef. В последних случаях объявления могут использовать тег структуры без предварительного определения типа структуры, но все же определение должно находиться в пределах видимости объявления.
Список объявлений элементов <member-declaration-list>- это одно или более объявлений переменных или битовых полей. Каждая переменная, объявленная в этом списке, называется элементом структурного типа. Объявления переменных списка имеют тот же самый синтаксис, что и объявления переменных обсуждаемых в этой главе, за исключением того, что объявления не могут содержать спецификаторов класса памяти или инициализаторов. Элементы структуры могут быть любого типа: основного, массивом, указателем, совмещением или структурой.
Элемент не может иметь тип структуры, в которой он появляется. Однако, элемент может быть объявлен, как указатель на тип структуры, в которую он входит, позволяя создавать списочные структуры.
Объявления битовых полей имеют следующий синтаксис:
<type-specifier>[<identifier>]:<constant-expression>; Битовое поле состоит из некоторого числа бит, специфицированных константным выражением- <constant- expression>. Для битового поля спецификатор типа <type- specifier> должен специфицировать беззнаковый целый тип, а константное выражение должно быть неотрицательной целой величиной. Массивы битовых полей, указатели на битовые поля и функции, возвращающие битовые поля не допускаются. Идентификатор- <identifier> именует битовое поле. Неименованное битовое поле, чей размер специфицируется как нулевой, имеет специальное назначение: оно гарантирует, что память для следующей переменной объявления будет начинаться на границе int.
Идентификаторы элементов внутри объявляемой структуры должны быть уникальными. Идентификаторы элементов внутри разных структур могут совпадать. В пределах той же самой видимости теги структур должны отличаться от других тегов (тегов других структур, совмещений и перечислений).
Переменные (элементы) структуры запоминаются последовательно в том же самом порядке, в котором они объявляются: первой переменной соответствует самый младший адрес памяти, а последнейсамый старший. Память каждой переменной начинается на границе свойственной ее типу. Поэтому могут появляться неименованные участки между соседними элементами.
Битовые поля не располагаются на пересечении границ, обявленных для них типов. Например, битовое поле, объявленое с типом unsigned int, упаковывается или в пространстве, оставшимся от предидущего unsigned int или начиная с нового unsigned int.
Примеры
/**************** Example 1 ****************/
struct {
float x,y;
} complex;
/**************** Example 2 *****************/
struct employee {
char name[20];
int id;
long class;
} temp;
/**************** Example 3 ******************/
struct employee student, faculty, staff;
/**************** Example 4 ******************/ struct sample {
char c;
float *pf;
struct sample *next;
} x;
/***************** Example 5 ******************/
struct {
unsigned icon : 8;
unsigned color : 4; unsigned underline : 1; unsigned blink : 1;
} screen[25][80];
В первом примере объявляется переменная с именем complex типа структура. Эта структура состоит из двух элементов x и y типа float. Тип структуры не поименован.
Во втором примере объявляется переменная с именем temp типа структура. Структура состоит из трех элементов с именами name, id и class. Элемент с именем name- это массив иэ 20- ти элементов типа char. элементы с именами id и class- это простые переменные типа int и long соответственно. Идентификатор employee является тегом структуры.
В третьем примере объявлены три переменных типа структура с именами: student, faculty и staff. Каждая из структур состоит из трех элементов одной и той же конструкции. Элементы определены при объявлении типа структуры с тегом employee в предыдущем примере.
В четвертом примере объявляется переменная с именем x типа структура. Первые два элемента структуры представлены переменной c типа char и указателем pf на величину типа float. Третий элемент с именем next объявляются как указатель на описываемую структуру sample.
В пятом примере объявляется двумерный массив поименованный screen, элементы которого имеют структурный тип. Массив состоит из 2000 элементов и каждый элементэто отдельная структура, состоящая из четырех элементов типа bit-fild с именами icon, color, underline и blink.
Синтаксис: union[<tag>]{<member-declaration-list>}<declarator>[,<declarator>...]; union<tag><declarator>[,<declarator>...];
Объявление совмещения определяет имя переменной совмещения и специфицирует множество переменных, называемых элементами совмещения, которые могут быть различных типов. Переменная с типом совмещения запоминает любую отдельную величину, определяемую набором элементов совмещения.
Объявление совмещения имеет тот же самый синтаксис, как и объявление структуры, за исключением того, что она начинается с ключевого слова union вместо ключевого слова struct. Для объявления совмещения и структуры действуют одни и те же правила, за исключением того, что в совмещении не допускаются элементы типа битовых полей.
Память, которая соответствует переменной типа совмещение, определяется величиной для размещения любого отдельного элемента совмещения.
Когда используется наименьший элемент совмещения, то переменная типа совмещения может содержать неиспользованное пространство. Все элементы совмещения запоминаются в одном и том же пространстве памяти переменной, начиная с одного и того же адреса. Запомненные значения затираются каждый раз, когда присваивается значение очередного элемента совмещения.
Примеры:
/************** Example 1 ********************/
union sign {
int svar;
unsigned uvar;
} number;
/************** Example 2 ********************/
union {
char *a, b;
float f[20];
} jack;
/*************** Example 2 *******************/
union {
struct {
char icon;
unsigned color : 4;
} window1, window2, window3, window4;
} screen[25][80];
В первом примере объявляется переменная типа совмещения, поименованная number. Список элементов совмещения состоит из двух объявлений переменных: svar типа int и uvar типа unsigned. Это объявление позволяет запоминать текущее значение number в знаковом или беззнаковом виде. Тип совмещения поименован идентификатором sign.