Для соответствующего компилятора перечисляемая константа всегда имеет тип int
(эквивалентно signed int
). Но такие константы обычно не хранятся в памяти, поэтому их тип, вероятно, не окажет большого влияния на требования к памяти.
Объявленный объект перечисляемого типа имеет сам перечисляемый тип, который совместим с char
или с некоторым целочисленным типом со знаком или без знака. Выбор типа определяется реализацией (т. е. компилятор может выбрать, но он должен задокументировать, как он делает выбор); единственное требование состоит в том, что тип должен быть способен хранить значения всех констант.
По общему признанию, странно, что константы имеют тип int
, а не перечисляемый тип, но именно так определен язык (причины исторические, а в C++ другие правила).
Например, учитывая:
enum foo { x, y, z };
enum foo obj;
obj = z;
выражение z
имеет тип int
и имеет значение 2 (точно так же, как десятичная константа 2
), но объект obj
имеет тип enum foo
и может иметь размер всего один байт, в зависимости от компилятора. Назначение obj = z;
включает неявное преобразование из int
в enum foo
(для этого преобразования может потребоваться или не потребоваться дополнительный код).
Некоторые компиляторы могут предоставлять нестандартный способ указания типа, который будет выбран для перечисляемого типа. Некоторые могут даже каким-то образом нарушать стандарт. Обратитесь к документации вашего компилятора, распечатайте значение sizeof (enum foo)
и, при необходимости, проверьте сгенерированный код.
Вполне вероятно, что ваш компилятор будет принимать разумные решения в рамках ограничений, налагаемых языком. Для компилятора, предназначенного для встраиваемых систем с недостаточным объемом памяти, особенно вероятно, что компилятор либо выберет небольшой тип, либо позволит вам указать его. Обратитесь к документации вашего компилятора.
Как предполагает ответ Яна, если вы хотите самостоятельно контролировать использование памяти, вы можете использовать объекты char
или unsigned char
. Однако вы все равно можете использовать определение enum
для определения констант. Например:
enum { x, y, z }; // No tag, so you can't declare objects of this type
typedef unsigned char foo; // an enum_foo object is guaranteed to be 1 byte
foo obj = z;
Ссылка: раздел 6.7.2.2 стандарта C. Ссылка на 1,7-мегабайтный PDF-файл последнего проекта стандарта ISO C 2011 года; этот конкретный раздел существенно не изменился с 1989 года.
person
Keith Thompson
schedule
04.04.2012