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?
strategy
avoir 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 unemain()
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.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.enum strategy { ... };
définit un type énuméré nomméenum strategy
, oùstrategy
est 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.Réponses:
La déclaration d'une variable enum se fait comme ceci:
Cependant, vous pouvez utiliser a
typedef
pour raccourcir les déclarations de variables, comme ceci:Avoir une convention de dénomination pour distinguer les types et les variables est une bonne idée:
la source
enum MyEnum {} myVar;
puis utiliser la variablemyVar
comme suit:myVar = SOMEENUMCONSTANT;
Il convient de souligner que vous n'avez pas besoin d' un
typedef
. Vous pouvez simplement le faire comme suitC'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 utiliserenum strategy
. Avec lui, vous pouvez simplement direstrategy
.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 stat
lastat
fonction: 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.la source
enum
mot - clé sur les deux lignes.enum strategy { RANDOM, IMMEDIATE, SEARCH };
alors quand vous voulez une instance de cette énumération: `enum strategy myEnum;Vous essayez de déclarer
strategy
deux fois, et c'est pourquoi vous obtenez l'erreur ci-dessus. Les œuvres suivantes sans aucune plainte (compilé avecgcc -ansi -pendantic -Wall
):Si au lieu de ce qui précède, la deuxième ligne a été remplacée par:
À partir des avertissements, vous pouvez facilement voir votre erreur:
Ainsi, le compilateur a pris
strategy = IMMEDIATE
pour une déclaration d'une variable appeléestrategy
avec le type par défautint
, 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:la source
Quand tu dis
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:
la source
Comme écrit, il n'y a rien de mal avec votre code. Êtes-vous sûr de ne pas avoir fait quelque chose comme
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?
la source
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 direint strategy = IMMEDIATE;
, à quel moment le conflit s'est produit.@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
,b
etc
) qui sont des nombres entiers avec des valeurs0
,1
et2
respectivement, mais quand nous utilisonsenum
c'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:et cela sortira
1
.Cela sera également valable:
et affichera la même chose qu'avant.
Si tu fais ça:
vous aurez une erreur, mais si vous faites cela:
vous n'aurez aucune erreur.
tu peux le faire:
et
aa
sera une variable entière avec une valeur0
. mais vous pouvez aussi le faire:et aura le même effet (c'est-à-dire
aa
être unint
avec0
valeur).vous pouvez également faire ceci:
et
aa
seraint
de valeur7
.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 desint
variables avec l'utilisation deenum
:son utilisation
typedef
est pour vous éviter d'écrire à chaque foisenum tag1
pour définir une variable. Avectypedef
vous pouvez simplement taperTag1
:Vous pouvez également avoir:
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:au lieu de
la source
Il convient de mentionner qu'en C ++, vous pouvez utiliser "enum" pour définir un nouveau type sans avoir besoin d'une instruction typedef.
Je trouve cette approche beaucoup plus conviviale.
[edit - clarifié le statut C ++ - je l'avais à l'origine, puis je l'ai supprimé!]
la source
typedef
, soit spécifier égalementenum
dans la déclaration de variable: enum Strategy {RANDOM, IMMEDIATE, SEARCH}; ... enum Strategy myStrategy = IMMEDIATE;enum Strategy
. Je l'ai fait, voir ci-dessous.Il semble y avoir une confusion au sujet de la déclaration.
Quand
strategy
vient avant{RANDOM, IMMEDIATE, SEARCH}
comme dans ce qui suit,vous créez un nouveau type nommé
enum strategy
. Cependant, lors de la déclaration de la variable, vous devez vous utiliserenum strategy
. Vous ne pouvez pas simplement utiliserstrategy
. Donc, ce qui suit n'est pas valide.Tandis que, ce qui suit est valide
Lorsque
strategy
vient après{RANDOM, IMMEDIATE, SEARCH}
, vous créez une énumération anonyme, puis déclarezstrategy
être une variable de ce type.Alors maintenant, vous pouvez faire quelque chose comme
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 valideVous pouvez également combiner les deux définitions
Typedef
comme indiqué précédemment est utilisé pour créer une déclaration de variable plus courte.Vous venez de dire au compilateur que
enum {RANDOM, IMMEDIATE, SEARCH}
c'est synonyme destrategy
. Alors maintenant, vous pouvez librement utiliserstrategy
comme type de variable. Vous n'avez plus besoin de taperenum strategy
. Ce qui suit est valide maintenantVous pouvez également combiner Typedef avec le nom enum pour obtenir
Il n'y a pas beaucoup d' avantage d'utiliser cette méthode en dehors du fait que vous pouvez maintenant utiliser
strategy
et de manièreenum strategyName
interchangeable.la source
typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy
outypedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_type
. Est-ce que cela a un avantagetypedef enum {RANDOM, IMMEDIATE, SEARCH} strategy
? Envisageriez-vous de les ajouter à votre réponse, pour être complet?Si vous déclarez le nom pour l'énumération, aucune erreur ne se produira.
Si non déclaré, vous devez utiliser
typedef
:Il n'affichera pas d'erreur ...
la source
Ma construction préférée et la seule utilisée a toujours été:
Je crois que cela supprimera votre problème. L'utilisation d'un nouveau type est de mon point de vue l'option de droite.
la source
La réponse de Tarc est la meilleure.
Une grande partie de la discussion enum est un hareng rouge.
Comparez cet extrait de code: -
qui donne
avec celui-ci qui se compile sans problème.
La variable
strategy
doit ê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!
Exemple 2. DROIT.
Exemple 3. DROIT.
Exemple 4. DROIT.
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.
la source
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 ;
la source
new
est un mauvais choix d'identifiants dans la famille C car c'est un opérateur en C ++.C
Déclaration qui agit comme une définition provisoire d'un entier signé
s
avec un type complet et déclaration qui agit comme une définition provisoire d'un entier signéq
avec 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 identifiantsq
ets
peuvent être redéclarés avec la version incomplète ou complète du même typeint
ouenum stuff
plusieurs 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 completenum stuff
qu'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 stuff
est également présente dans la portée du fichier (utilisable avant et ci-dessous) ainsi qu'une déclaration de type avant (le typeenum stuff
peut 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 remplacera
rvalue0
,b
with-4
,c
with5
,d
with-2
,e
with-3
,f
with-1
etg
with-2
dans 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.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 c
doit être utilisé et nona c
. Étant donné que l'espace de noms des balises est distinct de l'espace de noms des identificateurs, ilenum a {a} b
est autorisé maisenum a {a, b} b
pas 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} b
n'est pas non plus autorisé car les noms de typedef font partie de l'espace de noms des identifiants.Le type de
enum bool
et les constantes suivent le modèle suivant en C:Cela compile bien en C:
C ++
En C ++, les énumérations peuvent avoir un type
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 ++.
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é.
Enum classes
enum struct
est identique àenum class
L'opérateur de résolution de portée peut toujours être utilisé pour les énumérations non étendues.
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
::w
et::a::w
la source