Какое значение имеет объект enums, если он установлен в значение, не равное любой из его соответствующих констант enums?
Рассмотрим следующий код:
enum foobar{ FOO = 1, BAR = 5 }; enum foobar baz = 5; enum foobar qux = 42;
Переменная baz
устанавливается на целочисленное значение 5
, а переменная qux
устанавливается на целочисленное значение 42
.
Я подозреваю, что переменная baz
будет содержать значение BAR
, но я не уверен в переменной qux
. Никакой константе enums не было присвоено значение 42
, так что происходит, когда переменная enum foobar
установлена на такое значение?
Является ли стандарт C99 явным о результатах?
Стандарт проекта C99 , судя по всему, не ограничивает перечислитель исключительно на значения его членов, но он говорит, что нулевой тип перечислений должен быть способен представлять значения всех его членов. Это описано в разделе 6.7.2.2
enums :
Каждый перечисленный тип должен быть совместим с символом char, целочисленным типом со знаком или беззнаковым целым типом. Выбор типа определяется реализацией, 110), но должен быть способен представлять значения всех членов enums.
и поэтому вы будете полагаться на поведение, определенное реализацией, если вы используете значение, большее, чем члены определяют. В случае со знаком целочисленного переполнения приводит к неопределенному поведению в соответствии с разделом 5
который гласит:
Если при оценке выражения возникает исключительное условие (т. Е. Если результат не определен математически или нет в диапазоне представляемых значений для его типа), поведение не определено.
Обычно мы видим, что enumsм присваиваются значения за пределами тех, которые указаны их членами, когда они используются для представления полей бит.
Переменная qux
не будет содержать ни одного из значений enum
s. Его значение будет равно 42 в базовом типе, который компилятор выбирает для представления foobar
, который определяется реализацией. Это не представляет проблемы, когда значение равно 42
, но это может стать проблемой, когда константа не соответствует типу, выбранному компилятором для вашего enums.
Одной из причин, почему компилятор позволяет присваивать значения, отличные от констант enum
является поддержка перечислений «флаг», когда ожидается, что константы будут объединены в побитовые операции:
enum foobar { foo = 1 , bar = 2 , baz = 4 } test = (foo | baz);
Переменная test
выше содержит значение 5
, которое не соответствует какой-либо из констант enum
.
enum foobar{ FOO = 1, BAR = 5 }; enum foobar baz = 5;
заявление baz
эквивалентно:
enum foobar baz = BAR;
поскольку BAR
является значением int
5
.
Это заявление также справедливо:
enum foobar qux = 42;
C говорит, что тип enum
представляет собой целочисленный тип, достаточно большой для представления всех его констант enums. Если тип enum
недостаточно велик, значение преобразуется в целочисленный тип enums как для каждого целочисленного типа в соответствии с правилами целочисленного преобразования (c99, 6.3.1.3). Это целочисленное преобразование может быть определено реализацией (см. 6.3.1.3p3).