Quelle est la taille d'une énumération en C?

140

Je crée un ensemble de valeurs d'énumération, mais j'ai besoin que chaque valeur d'énumération ait une largeur de 64 bits. Si je me souviens bien, un enum a généralement la même taille qu'un int; mais je pensais avoir lu quelque part que (au moins dans GCC) le compilateur peut faire l'énumération de toute largeur nécessaire pour contenir leurs valeurs. Alors, est-il possible d'avoir une énumération de 64 bits de large?

mipadi
la source
1
Donc si je comprends bien, 2 ^ 32 énumérations ne vous suffisent pas? Ou est-ce un problème d'alignement, pourquoi avez-vous besoin de 64 au lieu de 32, je suis très curieux.
jokoon
1
@jokoon: Honnêtement, je ne m'en souviens plus. Je pense que je voulais que les énumérations contiennent des valeurs supérieures à 2 ^ 32-1.
mipadi le
Une utilisation serait si vous aviez besoin d'une union entre une énumération et un pointeur.
Demi

Réponses:

97

Il enumest garanti que An est suffisamment grand pour contenir des intvaleurs. Le compilateur est libre de choisir le type réel utilisé en fonction des constantes d'énumération définies afin de pouvoir choisir un type plus petit s'il peut représenter les valeurs que vous définissez. Si vous avez besoin de constantes d'énumération qui ne rentrent pas dans un, intvous devrez utiliser des extensions spécifiques au compilateur pour ce faire.

Robert Gamble
la source
12
Votre première phrase semble entrer en conflit avec la dernière. La contrainte selon laquelle an enumdoit être plus grand que an intou plus petit? Après la réponse de @MichaelStum, votre première phrase devrait être "An enumest garanti uniquement pour entrer dans une intvaleur."
HaskellElephant
En tant que hack de mise en œuvre horrible sur deux plates-formes complémentaires (est-ce que tous les systèmes de nos jours?), Vous pouvez forcer une énumération à être aussi grande qu'un int en vous assurant qu'elle contient des valeurs négatives. Pas une technique recommandée cependant.
persiflage le
7
Cette réponse semble suggérer qu'une énumération est aussi grande qu'un int. La réponse de Michael Stum , qui fait référence à C99, dit qu'une énumération peut être aussi petite qu'un char.
Frank Kusters
3
La première phrase de cette réponse est incorrecte. Il enumest seulement garanti que la taille de l 'est suffisamment grande pour contenir la valeur du plus grand énumérateur de l'énumération.
MM du
91

Tiré de la norme C actuelle (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Spécificateurs d'énumération
[...]
Contraintes
L'expression qui définit la valeur d'une constante d'énumération doit être une expression de constante entière qui a une valeur représentable comme un int.
[...]
Chaque type énuméré doit être compatible avec char, un type entier signé ou un type entier non signé. Le choix du type est défini par l'implémentation, mais doit être capable de représenter les valeurs de tous les membres de l'énumération.

Non pas que les compilateurs soient bons pour suivre la norme, mais essentiellement: Si votre enum contient autre chose qu'un int, vous êtes dans un "comportement non pris en charge profond qui peut revenir vous mordre dans un an ou deux" territoire.

Michael Stum
la source
3
ayant seulement cela, ce qui suit est valide je pense: enum {LAST = INT_MAX, LAST1, LAST2}; donc LAST2 n'est pas représentable dans int, mais il n'y avait pas d'expression le définissant.
Johannes Schaub - litb
4
Dans le PDF actuel, il définit que: "Les identificateurs dans une liste d'énumérateurs sont déclarés comme des constantes de type int [...]". J'ai omis cela pour le rendre pas trop bavard.
Michael Stum
2
Notez " un type entier signé ou un type entier non signé". Pas forcément int. shortet longsont également des types entiers, et quel que soit le choix de l'implémentation, toutes les valeurs doivent correspondre (" doit être capable de représenter les valeurs de tous les membres de l'énumération").
3
Notable: la constante d'énumération et le type énuméré ne sont pas la même chose . Les premiers sont le contenu de la liste de déclaration d'énumération, les seconds sont la variable réelle. Ainsi, alors que les constantes d'énumération doivent l'être int, la variable d'énumération réelle peut être d'un autre type. Il s'agit d'une incohérence bien connue dans la norme.
Lundin le
1
Pour clarifier le point de Lundin: For enum my_enum { my_value }, my_valueaura un type int, mais enum my_enumpeut avoir un type défini par l'implémentation qui doit au moins représenter toutes les valeurs d'énumération. Il my_valuepeut donc y avoir une conversion réduite en enum my_enum, mais il est garanti de ne pas dépasser.
P O'Conbhui
17

Bien que les réponses précédentes soient correctes, certains compilateurs ont des options pour briser la norme et utiliser le plus petit type qui contiendra toutes les valeurs.

Exemple avec GCC (documentation dans le manuel GCC ):

enum ord {
    FIRST = 1,
    SECOND,
    THIRD
} __attribute__ ((__packed__));
STATIC_ASSERT( sizeof(enum ord) == 1 )
Kevin Cox
la source
11
En fait, pour autant que je sache, cela ne brise pas la norme. Comme expliqué dans la réponse de Michael Stum, la norme permet au compilateur de choisir le type réel des énumérations, tant que toutes les valeurs correspondent.
sleske
2
J'ai travaillé avec des compilateurs MacOS C ++ qui exploitent la plage limitée de valeurs dans une énumération pour les stocker dans des types plus petits. Je ne me souviens pas s'il s'agissait de Metrowerks Codewarrior ou XCode. Cela fait partie de la norme C ++. Vous ne pouvez pas supposer sizeof (MyEnum) == sizeof (int) en général.
persiflage le
0

Définissez simplement la dernière valeur de l'énumération sur une valeur suffisamment grande pour lui donner la taille que vous souhaitez que l'énumération soit, elle devrait alors être de cette taille:

enum value{a=0,b,c,d,e,f,g,h,i,j,l,m,n,last=0xFFFFFFFFFFFFFFFF};
scirdan
la source
2
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire sur la façon et / ou pourquoi il résout le problème améliorerait la valeur à long terme de la réponse.
leopal le
-1

Nous n'avons aucun contrôle sur la taille d'une enumvariable. Cela dépend totalement de l'implémentation, et le compilateur donne la possibilité de stocker un nom pour un entier en utilisant enum, donc enumsuit la taille d'un entier.

Mehul Patel
la source
-1

En langage C, an enumest garanti d'avoir la taille d'un int. Il existe une option de compilation ( -fshort-enums) pour le rendre aussi court (ceci est principalement utile dans le cas où les valeurs ne dépassent pas 64 Ko). Il n'y a pas d'option de compilation pour augmenter sa taille à 64 bits.

rashok
la source
-6

Considérez ce code:

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

Il donnera 4 en sortie. Ainsi, quel que soit le nombre d'éléments qu'un enumcontient, sa taille est toujours fixe.

Tushan
la source
6
La réponse de Michael Stum est correcte. Ceci est spécifique au compilateur. Vous pouvez l'essayer vous-même avec IAR EWARM. IAR EWARM montre 1 pour votre exemple. S'il y a jusqu'à 255 éléments, il affiche toujours 1. Après avoir ajouté le 256ème élément, il passe à 2.
desowin
11
La question ne concerne pas le C ++.
Michas
4
choses importantes à réaliser avant d'écrire plus de C ou C ++: Ce n'est pas parce que cela compile que c'est légal selon le Standard. Ce n'est pas parce que vous obtenez un résultat donné que la norme dit que vous le ferez toujours ou que les autres utilisateurs le feront lorsqu'ils exécuteront votre code. Des questions comme celle-ci nécessitent une réponse qui référence le Standard ou au moins la spécification définie par l'implémentation pour un compilateur / ABI donné. Le simple fait de compiler et d'exécuter un programme et de voir un résultat un jour ne donne aucune leçon sur ces questions (et très peu sur quoi que ce soit d'autre).
underscore_d