Подписанность перечисления в C / C99 / C ++ / C ++ x / GNU C / GNU C99

Тип enum подписанный или неподписанный? Отличается ли подписанность перечислений между: C / C99 / ANSI C / C ++ / C ++ x / GNU C / GNU C99?

Спасибо


person osgx    schedule 05.04.2010    source источник


Ответы (2)


Перечисление гарантированно будет представлено целым числом, но фактический тип (и его подпись) зависят от реализации.

Вы можете принудительно представить перечисление типом со знаком, задав одному из перечислителей отрицательное значение:

enum SignedEnum { a = -1 };

В C ++ 0x можно явно указать базовый тип перечисления:

enum ShortEnum : short { a };

(В C ++ 0x также добавлена ​​поддержка перечислений с ограниченной областью видимости)

Для полноты я добавлю, что в Язык программирования C, 2-е изд. перечислители указаны как имеющие тип int (стр. 215). K&R не является стандартом C, поэтому он не является нормой для компиляторов ISO C, но он предшествует стандарту ISO C, так что это, по крайней мере, интересно с исторической точки зрения.

person James McNellis    schedule 05.04.2010
comment
Какая подпись на самом деле используется gcc? - person osgx; 05.04.2010
comment
@osgx: Я предполагаю, что это будет зависеть от количества счетчиков и диапазона их значений. Я правда не знаю. - person James McNellis; 05.04.2010
comment
Стандарт C также определяет, что каждая константа перечисления имеет тип int. Однако термин «константа перечисления» относится к константам значений, объявленным внутри блока enum { }. Переменная с типом enum может иметь любой целочисленный тип в C, например это может быть более короткий тип, чем int, если можно представить все значения. (Например, в GCC есть опция -fshort-enums для этого.) - person Arkku; 05.04.2010
comment
Термин перечислитель обычно понимается как константа перечисления, и AFAIK внутри enum{} у них никогда не бывает типа меньше, чем int, потому что компилятор еще не знает, какие значения будут следовать. - person MSalters; 06.04.2010
comment
@MSalters @Arkku: Верно; в C константы перечисления всегда имеют тип int. В C ++ они того же типа, что и их инициализатор, поэтому они могут быть любого целочисленного типа. - person James McNellis; 06.04.2010
comment
@osgx GCC решает во время компиляции, какую подпись применить к enum. У меня есть перечислитель со значениями от нуля и выше, и внутри функции проверяется, что значения этого перечислителя никогда не меньше нуля (он используется как индекс массива). GCC выдает предупреждение avServerApi.c:23: warning: comparison of unsigned expression < 0 is always false. Если я вставлю фиктивный -1 в enum, тогда предупреждение исчезнет, ​​когда счетчик будет подписан. - person Matt Clarkson; 28.07.2011

Это старый вопрос ... но я только что узнал следующее:

typedef unsigned ENUMNAME;  // this makes it unsigned in MSVC C 2015
typedef enum {v0, v1, v2, v3} ENUMNAME;

Вы можете использовать его как 2-битный беззнаковый индекс, например:

typedef struct {
  ENUMNAME i:2;
} STRUCTNAME;

Пробовал в GCC ARM - не работает.
Кроме того, WinDbg показывает STRUCTNAME.i как число, а не как v0-v3.

person aleksazr    schedule 15.06.2016
comment
Разве этот код не переопределяет тип ENUMNAME? - person U. Windl; 23.07.2021