2013-07-25 3 views
3

Может кто-нибудь объяснить, почему член X имеет другой размер, чем сам перечисленный тип, несмотря на то, что он явно определен как LL? Кажется противоречивым, что мне нужно сделать (enum e_x)X членом того же перечисляемого типа, чтобы быть уверенным, что он имеет тот же размер, что и тип.Размер перечислений

#include <stdio.h> 
#include <limits.h> 

enum e_x { X = 0LL, M = LLONG_MAX }; 

int main() { 
printf("%zu %zu %zu %zu\n", 
     sizeof X, 
     sizeof((enum e_x)X), 
     sizeof(enum e_x), 
     sizeof(long long)); 
} 

Выход:

4 8 8 8 

Ожидаемое:

8 8 8 8 

Как вы можете иметь дело с этим при переходе перечисления в функцию, которая использует va_arg?

ответ

4

Поведение, которое вы ожидаете, относится к C++, но не C. C не позволяет перечислять нумераторы int. От N1570 (~ С11) §6.7.2.2/2:

выражения, которое определяет значение константы перечисления должна быть постоянное выражением целого числа, которое имеет значение, представимый в качестве int.

Пункт 3 также говорит:

Идентификаторы в списке нумератора объявлены как константы, которые имеют тип int и могут появляться везде, где таковые допускаются.

Para 4 говорит:

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

sizeof X == sizeof(int) является следствием пункта 3, предположительно sizeof M == 4, а также по той же причине. По-видимому, реализация, по-видимому, выбрала 64-разрядный целочисленный тип для типа перечисления, поэтому sizeof(enum e_x) == 8 и sizeof((enum e_x)X)) == 8.

+0

Удивительно, 'sizeof M == 8'. В то же время 'gcc -pedantic' предупреждает, что' ISO C ограничивает значения перечислителя диапазоном 'int''. – Gepard

1

Это звучит как реальная проблема имеет дело с пропусканием длинного длинного аргумента функции с переменными аргументами:

«? Как вы можете иметь дело с этим при переходе перечисления в функцию, которая использует va_arg»

Возможно, вы не можете. В C функции с переменными аргументами ограничены в типах типов, с которыми они могут иметь дело. Целые типы подвергаются продвижению аргументов по умолчанию, которые изменяют большинство или все интегральные типы на int. Вот лучшая ссылка, которую я мог найти: http://www.eskimo.com/~scs/cclass/int/sx11c.html

Если вам нужно пройти длинный длинный путь, вы, вероятно, можете передать указатель на него.

+0

На самом деле, я просто изучаю все подробности о 'enum', потому что я пытаюсь найти для этого хорошее приложение. Поскольку все перечисления являются просто 'int', я не нахожу много оснований для использования перечисляемых типов ** в качестве членов структуры или аргументов функции. Даже если я объявляю член аргумента как type 'enum X', я все равно могу передать его целым числом. Таким образом, перечисления не имеют здесь никакой цели, кроме удобного и автоматического увеличения постоянных значений и, возможно, подсказки для программиста о том, какой диапазон 'int' ожидается. – Gepard

+0

Это справедливая оценка. В C чаще всего используются макросы препроцессора в качестве констант. – user1951747

0

ISO C ограничивает значения Enumerator в диапазоне int только .Если вам нужно перечисления констант, которые не помещаются в int вам нужно будет использовать расширения компилятора специфические для этого.

Что еще более важно, компилятор может выбрать меньший тип, если он может представлять значения, которые вы определяете.

Попробуйте компилировать с опцией -pedantic, вы получите сообщение об ошибке.

Смежные вопросы