Каков размер перечисления в C?

Я создаю набор значений перечисления, но мне нужно, чтобы каждое значение перечисления было шириной 64 бита. Если я правильно помню, enum обычно имеет тот же размер, что и int; но я думал, что где-то читал, что (по крайней мере, в GCC) компилятор может сделать перечисление любой ширины, которая им нужна для хранения своих значений. Итак, возможно ли иметь перечисление шириной 64 бита?

Так что, если я хорошо понимаю, вам мало 2 ^ 32 перечислений? Или это проблема выравнивания, зачем вам 64, а не 32, мне очень любопытно.

jokoon 06.05.2012 18:27

@jokoon: Честно говоря, я больше не помню. Думаю, я хотел, чтобы перечисления содержали значения больше 2 ^ 32-1.

mipadi 04.01.2013 21:37

Один из вариантов использования - если вам нужно объединение перечисления и указателя.

Demi 21.12.2013 05:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
144
3
201 558
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

enum гарантированно будет достаточно большим для хранения значений int. Компилятор может выбрать фактический используемый тип на основе определенных констант перечисления, поэтому он может выбрать меньший тип, если он может представлять определяемые вами значения. Если вам нужны константы перечисления, которые не подходят для int, вам нужно будет использовать для этого расширения, специфичные для компилятора.

Кажется, ваше первое предложение противоречит последнему. Есть ли ограничение, что enum должен быть больше, чем int, или меньше? После ответа @MichaelStum ваше первое предложение должно быть «enum гарантированно вписывается только в значение int».

HaskellElephant 20.06.2014 13:23

Как уродливая реализация, чувствительная к реализации на платформах с двумя дополнениями (это все системы в наши дни?), Вы можете заставить перечисление быть таким же большим, как int, убедившись, что оно содержит отрицательные значения. Однако это не рекомендуемый метод.

persiflage 23.09.2016 22:37

Этот ответ, по-видимому, предполагает, что размер enum равен int. Ответ Майкла Стума, который ссылается на C99, говорит, что перечисление может быть размером с char.

Frank Kusters 15.09.2017 09:46

Первое предложение этого ответа неверно. enum гарантированно будет достаточно большим, чтобы вместить значение самого большого перечислителя в перечислении.

M.M 28.09.2018 11:11

Взято из текущего стандарта C (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Enumeration specifiers
[...]
Constraints
The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an int.
[...]
Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration.

Не то чтобы компиляторы хорошо следовали стандарту, но по сути: если ваше перечисление содержит что-то еще, кроме int, вы находитесь в глубоком «неподдерживаемом поведении», которое может снова укусить вас через год или два.

Обновление: последний общедоступный проект стандарта C (C11): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1570.pdf содержит те же пункты. Следовательно, этот ответ все еще верен для C11.

имея только это, я думаю, верно следующее: enum {LAST = INT_MAX, LAST1, LAST2}; поэтому LAST2 не может быть представлен в int, но не было выражения, определяющего его.

Johannes Schaub - litb 14.12.2008 04:33

В реальном PDF он определяет следующее: «Идентификаторы в списке перечислителя объявляются как константы, имеющие тип int [...]». Я пропустил это, чтобы не было слишком многословно.

Michael Stum 14.12.2008 04:36

Примечание: «Целочисленный тип со знаком а или целочисленный тип без знака ан». Не обязательно int. short и long также являются целочисленными типами, и независимо от выбора реализации все значения должны соответствовать («должен может представлять значения всех членов перечисления»).

user824425 18.02.2016 20:45

Примечательно: константа перечисления и перечислимый типэто не то же самое. Первые являются содержимым списка объявлений enum, вторые - фактической переменной. Таким образом, хотя константы перечисления должны быть int, фактическая переменная перечисления может быть другого типа. Это известное несоответствие в стандарте.

Lundin 25.09.2017 14:56

Чтобы прояснить точку зрения Лундина: для enum my_enum { my_value }my_value будет иметь тип int, но enum my_enum может иметь тип, определенный реализацией, который должен, по крайней мере, представлять все значения перечисления. Таким образом, my_value может иметь сужающее преобразование в enum my_enum, но гарантированно не переполнится.

P O'Conbhui 26.11.2017 19:41

armcc предоставляет параметр компилятора --enum_is_int.

AlphaGoku 21.01.2020 13:43

Этот ответ более уместен, чем принятый.

LocalHost 20.10.2020 14:09

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

Пример с GCC (документация в Руководство GCC):

enum ord {
    FIRST = 1,
    SECOND,
    THIRD
} __attribute__ ((__packed__));
STATIC_ASSERT( sizeof(enum ord) == 1 )

На самом деле, насколько я понимаю, это не противоречит стандарту. Как объясняется в ответе Майкла Стума, стандарт позволяет компилятору выбирать фактический тип перечислений, если все значения подходят.

sleske 07.09.2015 13:27

Я работал с компиляторами MacOS C++, которые используют ограниченный диапазон значений в перечислении для хранения их в меньших типах. Не могу вспомнить, был ли это Metrowerks Codewarrior или XCode. Это в рамках стандарта C++. Вы не можете вообще предполагать sizeof (MyEnum) == sizeof (int).

persiflage 23.09.2016 22:29

Рассмотрим этот код:

enum value{a,b,c,d,e,f,g,h,i,j,l,m,n};
value s;
cout << sizeof(s) << endl;

На выходе будет 4. Таким образом, независимо от количества элементов, содержащихся в enum, его размер всегда фиксирован.

Ответ Майкла Стума правильный. Это зависит от компилятора. Вы можете попробовать это сами с IAR EWARM. IAR EWARM показывает 1 для вашего примера. Если имеется до 255 элементов, он все еще показывает 1. После добавления 256-го элемента он увеличивается до 2.

desowin 25.11.2015 10:43

Вопрос не в C++.

Michas 01.09.2016 02:12

важные вещи, которые необходимо понять, прежде чем писать больше на C или C++: просто потому, что он компилируется, не означает, что он законен в соответствии со стандартом. Тот факт, что вы получаете данный результат, не означает, что в Стандарте говорится, что вы всегда будете получать или что другие пользователи будут выполнять ваш код. На подобные вопросы нужен ответ, который ссылается на стандартную или определяемую реализацией спецификацию по меньшей мере для данного компилятора / ABI. Простая компиляция и запуск программы и получение одного результата за один день не дает никаких уроков по таким вопросам (и очень мало по чему-либо еще).

underscore_d 16.09.2018 19:20

У нас нет контроля над размером переменной enum. Это полностью зависит от реализации, и компилятор дает возможность сохранить имя для целого числа с помощью enum, поэтому enum соответствует размеру целого числа.

На языке C размер enum гарантированно равен int. Существует опция времени компиляции (-fshort-enums), чтобы сделать его максимально коротким (это в основном полезно, если значения не превышают 64 КБ). Во время компиляции нет возможности увеличить его размер до 64 бит.

Просто установите последнее значение перечисления на значение, достаточно большое, чтобы сделать его желаемым размером, тогда оно должно быть такого же размера:

enum value{a=0,b,c,d,e,f,g,h,i,j,l,m,n,last=0xFFFFFFFFFFFFFFFF};

Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.

leopal 15.01.2020 14:53

Это неправда. Компиляция вашего примера с помощью gcc 8.4.0: sizeof(a) - 4, а sizeof(last) - 8.

Mateo de Mayo 03.03.2021 19:28

typedef enum {a1 = 0, b1, c1, d1, f1, last1 = 0xFFFFFFFFFFFFFFFF} testing1; typedef enum {a2 = 0, b2, c2, d2, f2, last2 = 0xFFFFFFFF} testing2; размер переменной типа testing1 равен 8, а размер переменной type testing2 равен 4 ..

scirdan 04.03.2021 19:45

Другие вопросы по теме