Namespaces
Variants

Enumerations

From cppreference.net

Un type énuméré est un type distinct dont la valeur est une valeur de son type sous-jacent (voir ci-dessous), qui inclut les valeurs des constantes explicitement nommées ( constantes d'énumération ).

Table des matières

Syntaxe

Le type énuméré est déclaré en utilisant le spécificateur d'énumération suivant comme type-specifier dans la grammaire de déclaration :

enum attr-spec-seq  (optionnel) identifier  (optionnel) { enumerator-list } (1)
enum attr-spec-seq  (optionnel) identifier  (optionnel) : type { enumerator-list } (2) (depuis C23)
1) Déclare une énumération sans type sous-jacent fixe.
2) Déclare une énumération de type sous-jacent fixe type .

enumerator-list est une liste séparée par des virgules (avec virgule finale autorisée) (depuis C99) de enumerator , chacun ayant la forme :

enumeration-constant attr-spec-seq  (optionnel) (1)
enumeration-constant attr-spec-seq  (optionnel) = constant-expression (2)

identifier , enumeration-constant - identifiants introduits par cette déclaration
constant-expression - expression constante entière dont la valeur est représentable comme une valeur de type int (jusqu'en C23) . Si l'énumération a un type sous-jacent fixe, représentable comme une valeur du type (depuis C23)
attr-spec-seq - (C23) liste optionnelle d' attributs ,
  • appliquée à l'énumération entière si elle apparaît après enum ,
  • appliquée à l' énumérateur si elle apparaît après enumeration-constant

Comme avec struct ou union , une déclaration qui introduit un type énuméré et une ou plusieurs constantes d'énumération peut également déclarer un ou plusieurs objets de ce type ou de type dérivé de celui-ci.

enum color { RED, GREEN, BLUE } c = RED, *cp = &c;
// introduit le type enum color
// les constantes entières RED, GREEN, BLUE
// l'objet c de type enum color
// l'objet cp de type pointeur vers enum color

Explication

Chaque constante d'énumération qui apparaît dans le corps d'un spécificateur d'énumération devient une constante entière avec le type int (jusqu'en C23) dans la portée englobante et peut être utilisée partout où des constantes entières sont requises (par exemple comme étiquette de cas ou comme taille de tableau non-VLA).

Lors du traitement de chaque constante d'énumération dans la liste d'énumérateurs, le type de la constante d'énumération doit être :

  • le type précédemment déclaré, s'il s'agit d'une redéclaration de la même constante d'énumération ; ou,
  • le type énuméré, pour une énumération avec type sous-jacent fixe ; ou,
  • int , s'il n'y a pas de constantes d'énumération précédentes dans la liste d'énumérateurs et pas de = explicite avec une expression constante entière définissante ; ou,
  • int , si donné explicitement avec = et si la valeur de l'expression constante entière est représentable par un int ; ou,
  • le type de l'expression constante entière, si donné explicitement avec = et si la valeur de l'expression constante entière n'est pas représentable par int ; ou,
  • le type de la valeur de la dernière constante d'énumération avec 1 ajouté. Si une telle expression constante entière devait déborder ou envelopper la valeur de la constante d'énumération précédente par l'addition de 1, le type prend soit :
    • un type entier signé de taille appropriée (excluant les types entiers signés de précision binaire) capable de représenter la valeur de la constante d'énumération précédente plus 1 ; ou,
    • un type entier non signé de taille appropriée (excluant les types entiers non signés de précision binaire) capable de représenter la valeur de la constante d'énumération précédente plus 1.

Un type entier signé est choisi si la constante d'énumération précédente à laquelle on ajoute est de type entier signé. Un type entier non signé est choisi si la constante d'énumération précédente est de type entier non signé. S'il n'existe pas de type entier de taille appropriée décrit précédemment qui puisse représenter la nouvelle valeur, alors l'énumération n'a pas de type capable de représenter toutes ses valeurs.

(depuis C23)
enum color { RED, GREEN, BLUE } r = RED;
switch(r)
{
case RED:
    puts("rouge");
    break;
case GREEN:
    puts("vert");
    break;
case BLUE:
    puts("bleu");
    break;
}

Si enumeration-constant est suivi de = constant-expression , sa valeur est celle de cette expression constante. Si enumeration-constant n'est pas suivi de = constant-expression , sa valeur est la valeur immédiatement supérieure à celle de l'énumérateur précédent dans la même énumération. La valeur du premier énumérateur (s'il n'utilise pas = constant-expression ) est zéro.

enum Foo { A, B, C = 10, D, E = 1, F, G = F + C };
// A=0, B=1, C=10, D=11, E=1, F=2, G=12

L' identifiant lui-même, s'il est utilisé, devient le nom du type énuméré dans l'espace de noms des balises name space et nécessite l'utilisation du mot-clé enum (sauf s'il est typedef dans l'espace de noms ordinaire).

enum color { RED, GREEN, BLUE };
enum color r = RED; // OK
// color x = GREEN; // Erreur : color n'est pas dans l'espace de noms ordinaire
typedef enum color color_t;
color_t x = GREEN; // OK

Chaque type énuméré sans type sous-jacent fixe (depuis C23) est compatible avec l'un des : char , un type entier signé, ou un type entier non signé (à l'exclusion de bool et des types entiers à précision de bits) (depuis C23) . Le type compatible avec un type énuméré donné est défini par l'implémentation, mais quel qu'il soit, il doit être capable de représenter toutes les valeurs des énumérateurs de cette énumération. Pour toutes les énumérations avec un type sous-jacent fixe, le type énuméré est compatible avec le type sous-jacent de l'énumération. (depuis C23)

Le type de membre d'énumération pour un type énuméré sans type sous-jacent fixe lors de la finalisation est :

  • int si toutes les valeurs de l'énumération sont représentables comme un int ; ou,
  • le type énuméré.
(depuis C23)
Toutes les énumérations ont un type sous-jacent. Le type sous-jacent peut être explicitement spécifié en utilisant un spécificateur de type d'énumération et constitue son type sous-jacent fixe. S'il n'est pas explicitement spécifié, le type sous-jacent est le type compatible de l'énumération, qui est soit un type entier signé ou non signé, soit char . (depuis C23)

Les types énumérés sont des types entiers, et en tant que tels peuvent être utilisés partout où d'autres types entiers le peuvent, y compris dans les conversions implicites et les opérateurs arithmétiques .

enum { ONE = 1, TWO } e;
long n = ONE; // promotion
double d = ONE; // conversion
e = 1.2; // conversion, e is now ONE
e = e + 1; // e is now TWO

Notes

Contrairement aux struct ou aux union , il n'existe pas d'enums déclarés d'avance en C :

enum Color; // Erreur : pas de déclarations anticipées pour les énumérations en C
enum Color { RED, GREEN, BLUE };

Les énumérations permettent la déclaration de constantes nommées d'une manière plus pratique et structurée que ne le fait #define ; elles sont visibles dans le débogueur, respectent les règles de portée et participent au système de types.

#define TEN 10
struct S { int x : TEN; }; // Correct

ou

enum { TEN = 10 };
struct S { int x : TEN; }; // également valide

Depuis C23 constexpr peut être utilisé dans le même but :

constexpr int TEN = 10;
struct S { int x : TEN; }; // également valide

De plus, comme une struct ou une union n'établit pas sa portée en C, un type énumération et ses constantes d'énumération peuvent être introduits dans la spécification des membres de la première, et leur portée est la même que celle de la première, par la suite.

struct Element
{
    int z;
    enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
// le type enum State et ses constantes d'énumération restent visibles ici, par ex.
void foo(void)
{
    enum State e = LIQUID; // OK
    printf("%d %d %d ", e, oxygen.state, PLASMA); // affiche 1 2 3
}

Exemple

#include <stdio.h>
int main(void)
{
    enum TV { FOX = 11, CNN = 25, ESPN = 15, HBO = 22, MAX = 30, NBC = 32 };
    printf("List of cable stations:\n");
    printf(" FOX: \t%2d\n", FOX);
    printf(" HBO: \t%2d\n", HBO);
    printf(" MAX: \t%2d\n", MAX);
}

Sortie :

List of cable stations:
 FOX:   11
 HBO:   22
 MAX:   30

Références

  • Norme C23 (ISO/IEC 9899:2024):
  • 6.2.5/21 Types (p: 39)
  • 6.7.2.2 Spécificateurs d'énumération (p: 107-112)
  • Norme C17 (ISO/CEI 9899:2018):
  • 6.2.5/16 Types (p: 32)
  • 6.7.2.2 Spécificateurs d'énumération (p: 84-85)
  • Norme C11 (ISO/CEI 9899:2011) :
  • 6.2.5/16 Types (p: 41)
  • 6.7.2.2 Spécificateurs d'énumération (p: 117-118)
  • Norme C99 (ISO/CEI 9899:1999) :
  • 6.2.5/16 Types (p: 35)
  • 6.7.2.2 Spécificateurs d'énumération (p: 105-106)
  • Norme C89/C90 (ISO/CEI 9899:1990) :
  • 3.1.2.5 Types
  • 3.5.2.2 Spécificateurs d'énumération

Mots-clés

enum

Voir aussi

Documentation C++ pour déclaration d'énumération