Déjà lu cette question connexe , mais cherchait quelque chose d'un peu plus spécifique.
int
quelle que soit?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.
Je crois qu'il y a un drapeau si vous utilisez GCC.
-fshort-enums
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.
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.
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]
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.
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!