Comment définir un type énuméré (enum) en C?

272

Je ne sais pas quelle est la syntaxe appropriée pour utiliser les énumérations C. J'ai le code suivant:

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;

Mais cela ne se compile pas, avec l'erreur suivante:

error: conflicting types for strategy
error: previous declaration of strategy was here

Qu'est-ce que je fais mal?

lindelof
la source
7
Question vieille de plusieurs années, personne ne le verra probablement; mais pourquoi cela donne-t-il une erreur? Cela devrait fonctionner parfaitement bien car il s'agit de la question, autant que je sache.
Utkan Gezer
2
@Solver, pourquoi cette syntaxe est-elle incorrecte?
MCG
6
@MCQ, nécroisant le nécro nécro: La syntaxe présentée dans la question n'est pas erronée en C. Elle déclare strategyavoir un type énuméré anonyme et lui attribue l'une des valeurs déclarées de ce type. De plus, si j'encapsule le code présenté dans une main()fonction par ailleurs triviale , il se compile très bien pour moi, sans même un avertissement, avec gcc 4.4.7. Certaines réponses impliquent la même chose, mais pas en tant de mots.
John Bollinger
5
La plupart des réponses ne tiennent pas compte du fait que les deux lignes de code de la question ne sont pas simplement un extrait de code. Ils constituent l'intégralité du fichier source. Si ces deux lignes sont incluses dans le corps d'une fonction, il n'y a pas d'erreur. S'ils apparaissent à la portée du fichier, en dehors de toute déclaration de fonction, vous obtiendrez les erreurs sur lesquelles l'OP a demandé (ainsi que d'autres lorsque je l'ai essayé). Le problème fondamental est que le compilateur essaie de traiter strategy = IMMEDIATE;comme une déclaration. Il a une forme qui aurait été légale dans le C pré-ANSI, mais dans le C moderne, il est illégal. Les affectations ne sont pas autorisées à la portée du fichier.
Keith Thompson
3
@Solver: enum strategy { ... };définit un type énuméré nommé enum strategy, où strategyest la balise. enum { ... } strategy;définit un type énuméré anonyme (sans balise) et un seul objet de ce type nommé strategy. Les deux sont parfaitement légaux; ils signifient simplement des choses différentes.
Keith Thompson

Réponses:

377

La déclaration d'une variable enum se fait comme ceci:

enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy my_strategy = IMMEDIATE;

Cependant, vous pouvez utiliser a typedefpour raccourcir les déclarations de variables, comme ceci:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy my_strategy = IMMEDIATE;

Avoir une convention de dénomination pour distinguer les types et les variables est une bonne idée:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
RichieHindle
la source
1
Mais OP voulait une variable de type enum anonyme
osvein
Ne pourrais-je pas simplement taper enum MyEnum {} myVar;puis utiliser la variable myVarcomme suit:myVar = SOMEENUMCONSTANT;
Mushy
451

Il convient de souligner que vous n'avez pas besoin d' un typedef. Vous pouvez simplement le faire comme suit

enum strategy { RANDOM, IMMEDIATE, SEARCH };
enum strategy my_strategy = IMMEDIATE;

C'est une question de style si vous préférez typedef. Sans cela, si vous souhaitez faire référence au type d'énumération, vous devez utiliser enum strategy. Avec lui, vous pouvez simplement dire strategy.

Les deux façons ont leurs avantages et leurs inconvénients. Celui-ci est plus verbeux, mais conserve les identificateurs de type dans l'espace de noms des balises où ils n'entreront pas en conflit avec les identificateurs ordinaires (pensez à struct statla statfonction: ils ne sont pas en conflit non plus), et où vous voyez immédiatement que c'est un type. L'autre est plus court, mais apporte des identificateurs de type dans l'espace de noms ordinaire.

Johannes Schaub - litb
la source
6
Ce ne devrait pas être la réponse acceptée parce que c'est faux. Vous ne pouvez pas utiliser la stratégie d'énumération {...}; en C - vous pouvez et devez le faire en C ++.
Plus clair
19
@Clearer: ce code fonctionne parfaitement. Voici un exemple de travail: ideone.com/T0YV17 Notez qu'il utilise le enummot - clé sur les deux lignes.
RichieHindle
Ou "typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_t;" et le développeur utilisant l'énumération peut utiliser la convention de son choix.
Andy Nugent
cela fonctionne très bien: enum strategy { RANDOM, IMMEDIATE, SEARCH }; alors quand vous voulez une instance de cette énumération: `enum strategy myEnum;
user3629249
2
@AndyNugent ne fais pas ça! * Les types _t sont réservés par POSIX
osvein
58

Vous essayez de déclarer strategydeux fois, et c'est pourquoi vous obtenez l'erreur ci-dessus. Les œuvres suivantes sans aucune plainte (compilé avec gcc -ansi -pendantic -Wall):

#include <stdio.h>

enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;

int main(int argc, char** argv){
    printf("strategy: %d\n", strategy);

    return 0;
}

Si au lieu de ce qui précède, la deuxième ligne a été remplacée par:

...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...

À partir des avertissements, vous pouvez facilement voir votre erreur:

enums.c:5:1: warning: data definition has no type or storage class [enabled by default]
enums.c:5:1: warning: type defaults to int in declaration of strategy [-Wimplicit-int]
enums.c:5:1: error: conflicting types for strategy
enums.c:4:36: note: previous declaration of strategy was here

Ainsi, le compilateur a pris strategy = IMMEDIATEpour une déclaration d'une variable appelée strategyavec le type par défaut int, mais il y avait déjà une déclaration précédente d'une variable avec ce nom.

Cependant, si vous placez l'affectation dans la main()fonction, ce serait un code valide:

#include <stdio.h>

enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;

int main(int argc, char** argv){
    strategy=SEARCH;
    printf("strategy: %d\n", strategy);

    return 0;
}
Tarc
la source
48

Quand tu dis

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

vous créez une variable d'instance unique, appelée «stratégie» d'une énumération sans nom. Ce n'est pas une chose très utile à faire - vous avez besoin d'un typedef:

typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType; 
StrategyType strategy = IMMEDIATE;

la source
9
Pourquoi n'est-ce pas utile? Si je ne me soucie pas du nom du type, pourquoi devrais-je lui en donner un? La seule chose prévue ici était de nommer la variable, il est donc possible de lui attribuer de nouvelles valeurs.
MSalters
3
J'ai dit que ce n'était pas TRÈS utile et je ne le crois pas. Certes, je n'utilise pas ce modèle dans mon propre code. YMMV.
3
@HorseSMith Une énumération sans nom n'est pas très utile car vous ne pouvez pas avoir d'autre variable de ce type, ou paramètre de fonction ou valeur de retour. Si la seule variable est tout ce dont vous avez besoin, alors ça va.
Bob Stein
3
Quelqu'un qui n'utilise pas d'énumérations anonymes ne prouve pas qu'il ne sert à rien. Vous n'avez pas besoin de typedef. Certaines directives de code (kernel.org/doc/Documentation/CodingStyle) le découragent même.
martinkunev
2
Cette réponse est également trompeuse. La réponse de Tarc est la seule juste ici.
nightpool
13

Comme écrit, il n'y a rien de mal avec votre code. Êtes-vous sûr de ne pas avoir fait quelque chose comme

int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;

Sur quelles lignes les messages d'erreur pointent-ils? Quand il est écrit "la précédente déclaration de" stratégie "était là", qu'est-ce que "ici" et que montre-t-il?

John Bode
la source
6
Il l'a probablement fait strategy = IMMEDIATE;au niveau du fichier. Une affectation ne peut pas se produire à portée de fichier en dehors de toutes les fonctions. Le compilateur a donc essayé de tirer le meilleur parti de l'erreur et a supposé qu'il voulait dire int strategy = IMMEDIATE;, à quel moment le conflit s'est produit.
Johannes Schaub - litb
2
C'est la meilleure réponse, il y a tellement de confusion dans les autres réponses que c'est douloureux.
détendre le
12

@ThoAppelsin dans son commentaire à la question posée a raison. L'extrait de code publié dans la question est valide et sans erreur. L'erreur que vous avez doit être due à une autre syntaxe incorrecte à tout autre endroit de votre fichier source c. enum{a,b,c};définit trois constantes symboliques ( a, bet c) qui sont des nombres entiers avec des valeurs 0, 1et 2respectivement, mais quand nous utilisons enumc'est parce que nous ne nous soucions pas habituellement de la valeur entière spécifique, nous nous soucions plus sur la signification du nom de constante symbolique. Cela signifie que vous pouvez avoir ceci:

#include <stdio.h>
enum {a,b,c};
int main(){
  printf("%d\n",b);
  return 0;
}

et cela sortira 1.

Cela sera également valable:

#include <stdio.h>
enum {a,b,c};
int bb=b;
int main(){
  printf("%d\n",bb);
  return 0;
}

et affichera la même chose qu'avant.

Si tu fais ça:

enum {a,b,c};
enum {a,b,c};

vous aurez une erreur, mais si vous faites cela:

enum alfa{a,b,c};
enum alfa;

vous n'aurez aucune erreur.

tu peux le faire:

enum {a,b,c};
int aa=a;

et aasera une variable entière avec une valeur 0. mais vous pouvez aussi le faire:

enum {a,b,c} aa= a;

et aura le même effet (c'est-à-dire aaêtre un intavec 0valeur).

vous pouvez également faire ceci:

enum {a,b,c} aa= a;
aa= 7;

et aasera intde valeur 7.

parce que vous ne pouvez pas répéter la définition de constante symbolique avec l'utilisation de enum, comme je l'ai dit précédemment, vous devez utiliser des balises si vous souhaitez déclarer des intvariables avec l'utilisation de enum:

enum tag1 {a,b,c};
enum tag1 var1= a;
enum tag1 var2= b;

son utilisation typedefest pour vous éviter d'écrire à chaque fois enum tag1pour définir une variable. Avec typedefvous pouvez simplement taper Tag1:

typedef enum {a,b,c} Tag1;
Tag1 var1= a;
Tag1 var2= b;

Vous pouvez également avoir:

typedef enum tag1{a,b,c}Tag1;
Tag1 var1= a;
enum tag1 var2= b;

La dernière chose à dire est que puisque nous parlons de constantes symboliques définies, il est préférable d'utiliser des lettres majuscules lors de l'utilisation enum, c'est-à-dire par exemple:

enum {A,B,C};

au lieu de

enum {a,b,c};
roggc
la source
10

Il convient de mentionner qu'en C ++, vous pouvez utiliser "enum" pour définir un nouveau type sans avoir besoin d'une instruction typedef.

enum Strategy {RANDOM, IMMEDIATE, SEARCH};
...
Strategy myStrategy = IMMEDIATE;

Je trouve cette approche beaucoup plus conviviale.

[edit - clarifié le statut C ++ - je l'avais à l'origine, puis je l'ai supprimé!]

Roddy
la source
Oui, vous ne devez jamais utiliser typedef avec des énumérations (ou des structures, des unions, etc.) en C ++.
17
Cette question est pour C, pas pour C ++. En C, le code ci-dessus n'est pas valide - vous devez soit utiliser typedef, soit spécifier également enumdans la déclaration de variable: enum Strategy {RANDOM, IMMEDIATE, SEARCH}; ... enum Strategy myStrategy = IMMEDIATE;
Pavel Minaev, le
@pavel - mon mauvais. J'avais "en C ++" à l'origine, puis j'ai fait des recherches qui semblaient contredire cela.
Roddy
@ Pavel Je pense que ce devrait être une réponse distincte décrivant les avantages de l'utilisation enum Strategy. Je l'ai fait, voir ci-dessous.
Johannes Schaub - litb
8

Il semble y avoir une confusion au sujet de la déclaration.

Quand strategyvient avant {RANDOM, IMMEDIATE, SEARCH}comme dans ce qui suit,

enum strategy {RANDOM, IMMEDIATE, SEARCH};

vous créez un nouveau type nommé enum strategy. Cependant, lors de la déclaration de la variable, vous devez vous utiliser enum strategy. Vous ne pouvez pas simplement utiliser strategy. Donc, ce qui suit n'est pas valide.

enum strategy {RANDOM, IMMEDIATE, SEARCH};
strategy a;

Tandis que, ce qui suit est valide

enum strategy {RANDOM, IMMEDIATE, SEARCH};

enum strategy queen = RANDOM;
enum strategy king = SEARCH;
enum strategy pawn[100];

Lorsque strategyvient après {RANDOM, IMMEDIATE, SEARCH}, vous créez une énumération anonyme, puis déclarez strategyêtre une variable de ce type.

Alors maintenant, vous pouvez faire quelque chose comme

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = RANDOM;

Cependant, vous ne pouvez déclarer aucune autre variable de type enum {RANDOM, IMMEDIATE, SEARCH}car vous ne l'avez jamais nommée. Donc, ce qui suit n'est pas valide

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategy a = RANDOM;

Vous pouvez également combiner les deux définitions

enum strategy {RANDOM, IMMEDIATE, SEARCH} a, b;

a = RANDOM;
b = SEARCH;
enum strategy c = IMMEDIATE;

Typedef comme indiqué précédemment est utilisé pour créer une déclaration de variable plus courte.

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;

Vous venez de dire au compilateur que enum {RANDOM, IMMEDIATE, SEARCH}c'est synonyme de strategy. Alors maintenant, vous pouvez librement utiliser strategycomme type de variable. Vous n'avez plus besoin de taper enum strategy. Ce qui suit est valide maintenant

strategy x = RANDOM;

Vous pouvez également combiner Typedef avec le nom enum pour obtenir

typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;

Il n'y a pas beaucoup d' avantage d'utiliser cette méthode en dehors du fait que vous pouvez maintenant utiliser strategyet de manière enum strategyNameinterchangeable.

typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;

enum strategyName a = RANDOM;
strategy b = SEARCH;
Embrouiller
la source
1
Très bonne réponse. J'ai également rencontré des définitions d'énumérations écrites comme ceci: typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategyou typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_type. Est-ce que cela a un avantage typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy? Envisageriez-vous de les ajouter à votre réponse, pour être complet?
tjalling
Oui. J'ai modifié ma réponse. À ma connaissance, il n'y a pas d'avantage majeur dans le cas général.
Confondre
2
Très bien, votre réponse couvre tout cela maintenant, merci. Dommage que ce soit si loin dans la liste des réponses, pas du tout parce qu'il aborde explicitement la question d'origine, avec une explication appropriée.
tjalling
2

Si vous déclarez le nom pour l'énumération, aucune erreur ne se produira.

Si non déclaré, vous devez utiliser typedef:

enum enum_name {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;

Il n'affichera pas d'erreur ...

Peter Mortensen
la source
2

Ma construction préférée et la seule utilisée a toujours été:

typedef enum MyBestEnum
{
    /* good enough */
    GOOD = 0,
    /* even better */
    BETTER,
    /* divine */
    BEST
};

Je crois que cela supprimera votre problème. L'utilisation d'un nouveau type est de mon point de vue l'option de droite.

Sany
la source
1

La réponse de Tarc est la meilleure.

Une grande partie de la discussion enum est un hareng rouge.

Comparez cet extrait de code: -

int strategy;
strategy = 1;   
void some_function(void) 
{
}

qui donne

error C2501: 'strategy' : missing storage-class or type specifiers
error C2086: 'strategy' : redefinition

avec celui-ci qui se compile sans problème.

int strategy;
void some_function(void) 
{
    strategy = 1;   
}

La variable strategydoit être définie lors de la déclaration ou à l'intérieur d'une fonction, etc. Vous ne pouvez pas écrire de logiciels arbitraires - affectations en particulier - sur la portée globale.

Le fait qu'il ait utilisé enum {RANDOM, IMMEDIATE, SEARCH} au lieu de int n'est pertinent que dans la mesure où cela a troublé les gens qui ne peuvent pas voir au-delà. Les messages d'erreur de redéfinition dans la question montrent que c'est ce que l'auteur a fait de mal.

Alors maintenant, vous devriez pouvoir voir pourquoi le premier de l'exemple ci-dessous est faux et les trois autres sont corrects.

Exemple 1. FAUX!

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
void some_function(void) 
{
}

Exemple 2. DROIT.

enum {RANDOM, IMMEDIATE, SEARCH} strategy = IMMEDIATE;
void some_function(void) 
{
}

Exemple 3. DROIT.

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
void some_function(void) 
{
    strategy = IMMEDIATE;
}

Exemple 4. DROIT.

void some_function(void) 
{
    enum {RANDOM, IMMEDIATE, SEARCH} strategy;
    strategy = IMMEDIATE;
}

Si vous avez un programme de travail, vous devriez simplement pouvoir coller ces extraits dans votre programme et voir que certains compilent et d'autres non.

Ivan
la source
0

J'ai essayé avec gcc et j'ai trouvé pour mon besoin que j'étais obligé d'utiliser la dernière alternative, pour compiler sans erreur.

typedef enum state {a = 0, b = 1, c = 2} state ;

typedef enum state {a = 0, b = 1, c = 2} state;

typedef enum state old; // New type, alias of the state type.
typedef enum state new; // New type, alias of the state type.

new now     = a;
old before  = b;

printf("State   now = %d \n", now);
printf("Sate before = %d \n\n", before);
gg cg
la source
newest un mauvais choix d'identifiants dans la famille C car c'est un opérateur en C ++.
jww
0

C

enum stuff q;
enum stuff {a, b=-4, c, d=-2, e, f=-3, g} s;

Déclaration qui agit comme une définition provisoire d'un entier signé savec un type complet et déclaration qui agit comme une définition provisoire d'un entier signé qavec un type incomplet dans la portée (qui se résout en type complet dans la portée car la définition de type est présente n'importe où dans le portée) (comme toute définition provisoire, les identifiants qet speuvent être redéclarés avec la version incomplète ou complète du même type intou enum stuffplusieurs fois mais définis une seule fois dans la portée, c'est-à-dire int q = 3; et ne peuvent être redéfinis que dans une sous-portée, et utilisable uniquement après la définition). De plus, vous ne pouvez utiliser le type complet enum stuffqu'une fois dans la portée, car il agit comme une définition de type.

Une définition de type d'énumération du compilateur pour enum stuffest également présente dans la portée du fichier (utilisable avant et ci-dessous) ainsi qu'une déclaration de type avant (le type enum stuffpeut avoir plusieurs déclarations mais une seule définition / complétion dans la portée et peut être redéfini dans une sous-portée) . Il agit également comme une directive de compilation pour remplacer arvalue 0, bwith -4, cwith 5, dwith -2, ewith -3, fwith -1et gwith -2dans la portée actuelle. Les constantes d'énumération s'appliquent désormais après la définition jusqu'à la redéfinition suivante dans une énumération différente qui ne peut pas être au même niveau de portée.

typedef enum bool {false, true} bool;

//this is the same as 
enum bool {false, true};
typedef enum bool bool;

//or
enum bool {false, true};
typedef unsigned int bool;

//remember though, bool is an alias for _Bool if you include stdbool.h. 
//and casting to a bool is the same as the !! operator 

L'espace de noms de balise partagé par enum, struct et union est séparé et doit être préfixé par le mot-clé type (enum, struct ou union) en C c'est-à-dire après enum a {a} b, enum a cdoit être utilisé et non a c. Étant donné que l'espace de noms des balises est distinct de l'espace de noms des identificateurs, il enum a {a} best autorisé mais enum a {a, b} bpas parce que les constantes se trouvent dans le même espace de noms que les identificateurs de variables, l'espace de noms des identificateurs. typedef enum a {a,b} bn'est pas non plus autorisé car les noms de typedef font partie de l'espace de noms des identifiants.

Le type de enum boolet les constantes suivent le modèle suivant en C:

+--------------+-----+-----+-----+
|   enum bool  | a=1 |b='a'| c=3 |  
+--------------+-----+-----+-----+
| unsigned int | int | int | int |  
+--------------+-----+-----+-----+

+--------------+-----+-----+-----+
|   enum bool  | a=1 | b=-2| c=3 |  
+--------------+-----+-----+-----+
|      int     | int | int | int |  
+--------------+-----+-----+-----+

+--------------+-----+---------------+-----+
|   enum bool  | a=1 |b=(-)0x80000000| c=2 |
+--------------+-----+---------------+-----+
| unsigned int | int |  unsigned int | int |
+--------------+-----+---------------+-----+

+--------------+-----+---------------+-----+
|   enum bool  | a=1 |b=(-)2147483648| c=2 |
+--------------+-----+---------------+-----+
| unsigned int | int |  unsigned int | int |
+--------------+-----+---------------+-----+

+-----------+-----+---------------+------+
| enum bool | a=1 |b=(-)0x80000000| c=-2 |
+-----------+-----+---------------+------+
|    long   | int |      long     |  int |
+-----------+-----+---------------+------+

+-----------+-----+---------------+------+
| enum bool | a=1 | b=2147483648  | c=-2 |
+-----------+-----+---------------+------+
|    long   | int |      long     |  int |
+-----------+-----+---------------+------+

+-----------+-----+---------------+------+
| enum bool | a=1 | b=-2147483648 | c=-2 |
+-----------+-----+---------------+------+
|    int    | int |      int      |  int |
+-----------+-----+---------------+------+

+---------------+-----+---------------+-----+
|   enum bool   | a=1 | b=99999999999 | c=1 |
+---------------+-----+---------------+-----+
| unsigned long | int | unsigned long | int |
+---------------+-----+---------------+-----+

+-----------+-----+---------------+------+
| enum bool | a=1 | b=99999999999 | c=-1 |
+-----------+-----+---------------+------+
|    long   | int |      long     |  int |
+-----------+-----+---------------+------+

Cela compile bien en C:

#include <stdio.h>
enum c j;
enum c{f, m} p;
typedef int d;
typedef int c;
enum c j;
enum m {n} ;
int main() {
  enum c j;
  enum d{l};
  enum d q; 
  enum m y; 
  printf("%llu", j);
}

C ++

En C ++, les énumérations peuvent avoir un type

enum Bool: bool {True, False} Bool;
enum Bool: bool {True, False, maybe} Bool; //error

Dans cette situation, les constantes et l'identifiant ont tous le même type, bool, et une erreur se produira si un nombre ne peut pas être représenté par ce type. Peut-être = 2, ce qui n'est pas un bool. De plus, True, False et Bool ne peuvent pas être en minuscules, sinon ils se heurteront aux mots-clés de langue. Une énumération ne peut pas non plus avoir de type pointeur.

Les règles pour les énumérations sont différentes en C ++.

#include <iostream>
c j; //not allowed, unknown type name c before enum c{f} p; line
enum c j; //not allowed, forward declaration of enum type not allowed and variable can have an incomplete type but not when it's still a forward declaration in C++ unlike C
enum c{f, m} p;
typedef int d;
typedef int c; // not allowed in C++ as it clashes with enum c, but if just int c were used then the below usages of c j; would have to be enum c j;
[enum] c j;
enum m {n} ;
int main() {
  [enum] c j;
  enum d{l}; //not allowed in same scope as typedef but allowed here 
  d q;
  m y; //simple type specifier not allowed, need elaborated type specifier enum m to refer to enum m here
  p v; // not allowed, need enum p to refer to enum p
  std::cout << j;
}

Les variables enums en C ++ ne sont plus seulement des entiers non signés, etc., elles sont également de type enum et ne peuvent être affectées qu'à des constantes dans l'énumération. Cela peut cependant être rejeté.

#include <stdio.h>
enum a {l} c;
enum d {f} ;
int main() {
  c=0; // not allowed;
  c=l;
  c=(a)1;
  c=(enum a)4;
  printf("%llu", c); //4
}

Enum classes

enum struct est identique à enum class

#include <stdio.h>
enum class a {b} c;
int main() {
  printf("%llu", a::b<1) ; //not allowed
  printf("%llu", (int)a::b<1) ;
  printf("%llu", a::b<(a)1) ;
  printf("%llu", a::b<(enum a)1);
  printf("%llu", a::b<(enum class a)1) ; //not allowed 
  printf("%llu", b<(enum a)1); //not allowed
}

L'opérateur de résolution de portée peut toujours être utilisé pour les énumérations non étendues.

#include <stdio.h>
enum a: bool {l, w} ;
int main() {
  enum a: bool {w, l} f;
  printf("%llu", ::a::w);
}

Mais parce que w ne peut pas être défini comme autre chose dans la portée, il n'y a pas de différence entre ::wet::a::w

Lewis Kelsey
la source