¿Cuál es el tamaño de una enumeración en C?

140

Estoy creando un conjunto de valores de enumeración, pero necesito que cada valor de enumeración tenga 64 bits de ancho. Si recuerdo correctamente, una enumeración es generalmente del mismo tamaño que una int; pero pensé que leí en alguna parte que (al menos en GCC) el compilador puede hacer que la enumeración tenga el ancho que sea necesario para mantener sus valores. Entonces, ¿es posible tener una enumeración de 64 bits de ancho?

mipadi
fuente
1
Entonces, si entiendo bien, ¿2 ^ 32 enumeraciones no son suficientes para usted? O es una preocupación de alineación, ¿por qué necesita que sean 64 en lugar de 32? Tengo mucha curiosidad.
jokoon
1
@jokoon: Sinceramente, ya no lo recuerdo. Creo que quería que las enumeraciones contuvieran valores mayores que 2 ^ 32-1.
mipadi
Un uso sería si necesitara una unión entre una enumeración y un puntero.
Demi

Respuestas:

97

Una enumúnica se garantiza que sea lo suficientemente grande como para contener intvalores. El compilador es libre de elegir el tipo real utilizado en función de las constantes de enumeración definidas para que pueda elegir un tipo más pequeño si puede representar los valores que defina. Si necesita constantes de enumeración que no encajan en una int, deberá usar extensiones específicas del compilador para hacerlo.

Robert Gamble
fuente
12
Su primera oración parece estar en conflicto con la última. ¿Es la restricción que un enumdebería ser mayor que uno into menor? Siguiendo la respuesta de @MichaelStum, su primera oración debería ser "Un enumsolo se garantiza que encaja en un intvalor".
HaskellElephant
Como un truco sensible de implementación fea en dos plataformas complementarias (¿son todos los sistemas en estos días?), Puede forzar que una enumeración sea tan grande como un int asegurándose de que contenga valores negativos. Sin embargo, no es una técnica recomendada.
persiflage
77
Esta respuesta parece sugerir que una enumeración es tan grande como un int. La respuesta de Michael Stum , que hace referencia a C99, dice que una enumeración puede ser tan pequeña como a char.
Frank Kusters
3
La primera oración de esta respuesta es incorrecta. La enumúnica se garantiza que sea lo suficientemente grande como para mantener el valor de la mayor enumerador en la enumeración.
MM
91

Tomado del estándar C actual (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Especificadores de enumeración
[...]
Restricciones
La expresión que define el valor de una constante de enumeración debe ser una expresión constante entera que tenga un valor representable como int.
[...]
Cada tipo enumerado debe ser compatible con char, un tipo entero con signo o un tipo entero sin signo. La elección del tipo está definida por la implementación, pero debe ser capaz de representar los valores de todos los miembros de la enumeración.

No es que los compiladores sean buenos para seguir el estándar, pero esencialmente: si su enumeración contiene algo más que un int, está en un "comportamiento sin apoyo que puede volver a morderlo en un año o dos".

Michael Stum
fuente
3
teniendo solo eso, lo siguiente es válido, creo: enum {LAST = INT_MAX, LAST1, LAST2}; entonces LAST2 no es representable en int, pero no había una expresión que lo definiera.
Johannes Schaub - litb
44
En el PDF real, define que: "Los identificadores en una lista de enumeradores se declaran como constantes que tienen el tipo int [...]". Lo he omitido para que no sea demasiado detallado.
Michael Stum
2
Tenga en cuenta " un tipo entero con signo, o un tipo entero sin signo". No necesariamente int. shorty longson tipos enteros también, y cualquiera que sea la implementación que elija, todos los valores deben ajustarse (" será capaz de representar los valores de todos los miembros de la enumeración").
3
Notable: la enumeración constante y el tipo enumerado no es lo mismo . Los primeros son los contenidos de la lista de declaración enum, los últimos son la variable real. Entonces, aunque las constantes de enumeración deben ser int, la variable de enumeración real podría ser de otro tipo. Esta es una inconsistencia bien conocida en el estándar.
Lundin
1
Para aclarar el punto de Lundin: For enum my_enum { my_value }, my_valuetendrá tipo int, pero enum my_enumpuede tener un tipo definido de implementación que al menos debe representar todos los valores de enumeración. Por my_valuelo tanto, puede tener una conversión de reducción a enum my_enum, pero se garantiza que no se desborde.
P O'Conbhui
17

Si bien las respuestas anteriores son correctas, algunos compiladores tienen opciones para romper el estándar y utilizar el tipo más pequeño que contendrá todos los valores.

Ejemplo con GCC (documentación en el Manual de GCC ):

enum ord {
    FIRST = 1,
    SECOND,
    THIRD
} __attribute__ ((__packed__));
STATIC_ASSERT( sizeof(enum ord) == 1 )
Kevin Cox
fuente
11
En realidad, hasta donde puedo ver, esto no rompe el estándar. Como se explica en la respuesta de Michael Stum, el estándar permite al compilador elegir el tipo real de las enumeraciones, siempre y cuando se ajusten todos los valores.
sleske
2
He trabajado con compiladores MacOS C ++ que explotan el rango limitado de valores en una enumeración para almacenarlos en tipos más pequeños. No recuerdo si fue Metrowerks Codewarrior o XCode. Esto está dentro del estándar C ++. No puede asumir sizeof (MyEnum) == sizeof (int) en general.
persiflage
0

Simplemente establezca el último valor de la enumeración en un valor lo suficientemente grande como para que sea del tamaño que desea que sea la enumeración, entonces debería ser ese tamaño:

enum value{a=0,b,c,d,e,f,g,h,i,j,l,m,n,last=0xFFFFFFFFFFFFFFFF};
scirdan
fuente
1
Si bien este código puede responder la pregunta, proporcionar un contexto adicional con respecto a cómo y / o por qué resuelve el problema mejoraría el valor a largo plazo de la respuesta.
leopal
-1

No tenemos control sobre el tamaño de una enumvariable. Depende totalmente de la implementación, y el compilador da la opción de almacenar un nombre para un número entero enum, por enumlo que sigue el tamaño de un número entero.

Mehul patel
fuente
-1

En lenguaje C, enumse garantiza que an tendrá el tamaño de an int. Hay una opción de tiempo de compilación ( -fshort-enums) para que sea breve (esto es principalmente útil en caso de que los valores no sean más de 64K). No hay una opción de tiempo de compilación para aumentar su tamaño a 64 bits.

rashok
fuente
-6

Considera este código:

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

Dará 4 como salida. Entonces, no importa la cantidad de elementos que enumcontenga, su tamaño siempre es fijo.

tushan
fuente
66
La respuesta de Michael Stum es correcta. Esto es específico del compilador. Puede probarlo usted mismo con IAR EWARM. IAR EWARM muestra 1 para su ejemplo. Si hay hasta 255 elementos, todavía muestra 1. Después de agregar el elemento 256, sube a 2.
desowin
11
La pregunta no es sobre C ++.
Michas el
44
cosas importantes a tener en cuenta antes de escribir más C o C ++: solo porque compila no significa que sea legal según el Estándar. El hecho de que obtenga un resultado determinado no significa que el Estándar dice que siempre lo hará o que otros usuarios lo harán cuando ejecuten su código. Preguntas como esta necesitan una respuesta que haga referencia al Estándar o al menos a la especificación definida por la implementación para un compilador / ABI dado. Simplemente compilar y ejecutar un programa y ver un resultado en un día no transmite ninguna lección sobre tales preguntas (y muy poco sobre cualquier otra cosa).
underscore_d