6.3  Перечисления

Тип перечисления служит для обеспечения мнемонических идентификаторов целочисленных переменных. Например, следующее объявление:

enum days { sun, mon, tues, wed, thur, fri, satanyday;

устанавливает уникальный интегральный тип enum days, переменную anyday этого типа и набор нумераторов (sun,mon,…), которым соответствуют целочисленные константы.

Идентификаторы, используемые в списке нумераторов, неявно получают тип signed char, unsigned char или int, в зависимости от значений нумераторов. Если все значения могут быть представлены типом signed или unsigned char, то это и будет типом каждого нумератора.

В языке С переменной перечислимого типа может быть присвоено любое значение типа int, кроме этого никакого контроля типа не выполняется. В языке С++ переменной перечислимого типа может присваиваться только значение одного из ее нумераторов. Например:

anyday = mon;    // так можно

anyday = 1;         // так нельзя, даже хотя mon == 1

Идентификатор days является тегом перечислимого типа, который можно использовать в последующих объявлениях переменных перечислимого типа enum days. Например:

enum days payday, holiday; // объявление двух переменных.

В языке С++ ключевое слово enum можно опустить, если в пределах данного контекста имя days не дублируется.

Как и в случае объявлений struct и union, если далее переменные данного типа enum не требуются, тег может быть опущен:

enum { sun, mon, tues, wed, thur, fri, sat } anyday; /* анонимный тип enum */

Подробное описание констант перечислимого типа было выполнено в разд. 2 и 4.

Нумераторы, перечисленные внутри фигурных скобок, называются перечислимыми константами. Каждой из них назначается фиксированное значение. При отсутствии явно заданных инициализаторов первый нумератор (sun) устанавливается в ноль, а каждый последующий нумератор имеет значение на единицу больше, чем предыдущий (mon = 1, tue = 2 и т.д.).

При наличии явных интегральных инициализаторов можно устанавливать один или более нумераторов в конкретные значения. Любые последующие имена без инициализаторов будут получать приращение в единицу. Например, в следующем объявлении:

/* выражение инициализатора может включать в себя нумераторы,

объявленные ранее */

enum coins { penny = 1, tuppence, nickel = penny + 4, dime =10,

                    quarter = nickel * nickel } smallchange;

компонента tuppence примет значение 2,  компонента nickel – значение 5, а quarter – значение 25.

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

Тип enum может участвовать во всех конструкциях, допускающих использование типов int. Например:

enum days { sun, mon, tues, wed, thur, fri, sat } anyday;

enum days payday;

typedef enum days DAYS;

DAYS  *daysptr;

int i = tues;

anyday = mon;         // так можно

*daysptr = anyday;  // так можно

mon = tues;    // неверно: mon – это константа

Теги перечислений разделяют пространство имен с тегами структур и объединений. Нумераторы разделяют пространство имен с обычными идентификаторами переменных:

int mon = 11;

{

enum days { sun, mon, tues, wed, thur, fri, sat } anyday;

/* нумератор mon скрывает внешнее объявление int mon */

struct days { int i, j;); // неверно: дублируется тег days

double sat; // неверно: переопределение sat

}

mon = 12;   // снова в контексте int mon

В языке С++ нумераторы, объявленные в пределах класса, имеют контекст этого класса.

Объявление определения

type идентификатор [<константное выражение>]

объявляет одномерный массив, состоящий из элементов одинакового типа type. Массив состоит из непрерывной области памяти, достаточной по размеру, чтобы разместить все его элементы.

Если <константное выражение> – выражение, то при его вычислении должна получаться положительная целочисленная константа. Получившееся значение представляет собой число элементов массива. Каждый из элементов массива нумеруется от 0 до числа элементов массива минус единица. Количество элементов массива является важной характеристикой массива, но не его типа. Эта характеристика называется размерностью массива.

Объявление ссылки на массив начинается с ключевого слова extern. Например, объявление  определения и объявления ссылки на массив array выглядит так:

int array[3];  // Объявление определения;

extern int array[ ]; // Объявление ссылки;

Элементы массива могут быть явно инициализированы при объявлении определения. Например:

int array[3]= {1,2,3};  // Размерность массива  указывается явно;

int array[ ]= {1,2,3};  // Размерность массива определяется числом инициализаторов;

Возможна частичная инициализация массива. При этом значения получают первые элементы массива. Например:

int array[3]= {1,2};  // Инициализируются только первые два элемента;

Значение последнего элемента массива в общем случае не определено.

В объявлениях ссылки (со спецификатором extern)  размеры объявляемого массива можно не указывать, так как компилятор их не читает. Также в объявлениях ссылки нельзя инициализировать элементы массива.