web-dev-qa-db-fra.com

Spécifier la taille du type enum en C

Déjà lu cette question connexe , mais cherchait quelque chose d'un peu plus spécifique.

  • Existe-t-il un moyen d'indiquer à votre compilateur quelle est la largeur de votre enum?
  • Si oui, comment faites-vous? Je sais comment le spécifier en C #; est-ce pareil fait en C?
  • Cela vaudrait-il la peine d'être fait? Lorsque la valeur enum est transmise à une fonction, cette valeur sera-t-elle passée sous la forme d'une variable int quelle que soit?
26
Will

Y at-il un moyen de dire à votre compilateur précisément à quelle largeur vous voulez votre Enum d'être?

Dans le cas général non. Pas en standard C.

Cela vaudrait-il la peine d'être fait?

Ça dépend du contexte. Si vous parlez de passer des paramètres à des fonctions, alors non, cela ne vaut pas la peine d'être fait (voir ci-dessous). S'il s'agit d'économiser de la mémoire lors de la construction d'agrégats à partir de types enum, cela peut valoir la peine d'être fait. Cependant, en C, vous pouvez simplement utiliser un type entier de taille appropriée au lieu du type enum dans les agrégats. En C (par opposition à C++), les types enum et les types entiers sont presque toujours interchangeables.

Quand la valeur enum est passée à une fonction, sera-t-elle passée en tant que valeur de taille int indépendamment?

De nombreux compilateurs (la plupart) de nos jours transmettent tous les paramètres en tant que valeurs de la taille naturelle de Word pour la plate-forme matérielle donnée. Par exemple, sur une plate-forme 64 bits, de nombreux compilateurs transmettent tous les paramètres sous forme de valeurs 64 bits, quelle que soit leur taille réelle, même si le type int a 32 bits dans cette plate-forme -sized "valeur sur une telle plate-forme). Pour cette raison, il n’a aucun sens d’essayer d’optimiser les tailles d’énum pour le passage de paramètres.

17
AnT

Je crois qu'il y a un drapeau si vous utilisez GCC.

-fshort-enums

15
Nyx0uf

Vous pouvez le forcer à avoir au moins une certaine taille en définissant une valeur appropriée. Par exemple, si vous voulez que votre enum soit stocké avec la même taille qu'un int, même si toutes les valeurs peuvent tenir dans un char, vous pouvez faire quelque chose comme ça:

typedef enum {
    firstValue = 1,
    secondValue = 2,

    Internal_ForceMyEnumIntSize = MAX_INT
} MyEnum;

Notez cependant que le comportement peut dépendre de l'implémentation.

Comme vous le constatez, le fait de transmettre une telle valeur à une fonction entraîne son extension à un int de toute façon, mais si vous utilisez votre type dans un tableau ou une structure, sa taille aura de l'importance. Si vous vous souciez vraiment de la taille des éléments, vous devriez vraiment utiliser des types comme int8_t, int32_t, etc.

8
Kristopher Johnson

Il y a aussi un autre moyen si l'énum fait partie d'une structure:

struct something {
     :0;
   enum whatever field:CHAR_BIT;
     :0;
};

Le: 0; peut être omis si le champ enum est entouré de champs normaux. S'il existe un autre champ de bits avant, le: 0 forcera l'alignement d'octet sur l'octet suivant pour le champ qui le suit.

7

Dans certaines circonstances, cela peut être utile:

typedef uint8_t command_t;
enum command_enum
{
    CMD_IDENT                = 0x00,     //!< Identify command
    CMD_SCENE_0              = 0x10,     //!< Recall Scene 0 command
    CMD_SCENE_1              = 0x11,     //!< Recall Scene 1 command
    CMD_SCENE_2              = 0x12,     //!< Recall Scene 2 command
};

/* cmdVariable is of size 8 */
command_t cmdVariable = CMD_IDENT; 

D'une part, le type command_t a la taille 8 et peut être utilisé pour le type de paramètre de variable et de fonction . D'autre part, vous pouvez utiliser les valeurs enum pour l'affectation qui sont de type int par défaut, mais le compilateur les convertit immédiatement lorsqu'elles sont affectées à une variable de type command_t.

De plus, si vous faites quelque chose de non sécurisé, comme définir et utiliser un CMD_16bit = 0xFFFF,, le compilateur vous avertira par le message suivant:

avertissement: grand entier implicitement tronqué à un type non signé [-Woverflow]

0
Julien

Cela dépend des valeurs attribuées pour les enums.

Ex: Si la valeur supérieure à 2 ^ 32-1 est stockée, la taille allouée pour l'énumération globale passera à la taille suivante.

Stockez la valeur 0xFFFFFFFFFFFF dans une variable enum, elle vous avertira si vous tentez de compiler dans un environnement 32 bits (avertissement arrondi) Comme dans une compilation 64 bits, le résultat sera satisfaisant et la taille allouée sera de 8 octets.

0
user5057906

Comme @ Nyx0uf dit , GCC a un drapeau que vous pouvez définir:

-fshort-enums 

Attribuez à un type enum uniquement le nombre d'octets requis pour la plage déclarée de valeurs possibles. Plus précisément, le type enum est équivalent au type entier le plus petit qui dispose de suffisamment de place. 

Avertissement: le commutateur -fshort-enums force GCC à générer du code non compatible binaire avec le code généré sans ce commutateur. Utilisez-le pour vous conformer à une interface binaire d'application autre que celle par défaut. 

Source: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html

Excellente lecture pour des idées générales:https://www.embedded.fm/blog/2016/6/28/how-big-is-an-enum .
Intéressant ... remarquez la ligne que j'ai surlignée en jaune ci-dessous!

 enter image description here

0
Gabriel Staples