Ich bin mir nicht sicher, wie die Syntax für die Verwendung von C-Enums lautet. Ich habe folgenden Code:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
Dies wird jedoch nicht mit folgendem Fehler kompiliert:
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
Was mache ich falsch?
strategy
einen anonymen Aufzählungstyp und weist ihr einen der deklarierten Werte dieses Typs zu. Wenn ich den Code in eine ansonsten trivialemain()
Funktion einbinde, wird er für mich ohne Vorwarnung mit gcc 4.4.7 problemlos kompiliert. Einige der Antworten implizieren dasselbe, wenn auch nicht in so vielen Worten.strategy = IMMEDIATE;
als Deklaration zu behandeln . Es hat eine Form, die vor ANSI C legal gewesen wäre, aber im modernen C ist es illegal. Zuweisungen sind im Dateibereich nicht zulässig.enum strategy { ... };
einen Aufzählungstyp mit dem Namenenum strategy
, wobeistrategy
sich das Tag befindet.enum { ... } strategy;
definiert einen anonymen Aufzählungstyp (kein Tag) und ein einzelnes Objekt dieses Typs mit dem Namenstrategy
. Beide sind vollkommen legal; Sie bedeuten nur verschiedene Dinge.Antworten:
Das Deklarieren einer Enum-Variablen erfolgt folgendermaßen:
Sie können jedoch a verwenden
typedef
, um die Variablendeklarationen wie folgt zu verkürzen:Eine Namenskonvention zur Unterscheidung zwischen Typen und Variablen ist eine gute Idee:
quelle
enum MyEnum {} myVar;
die VariablemyVar
myVar = SOMEENUMCONSTANT;
Es ist erwähnenswert, dass Sie nicht brauchen ein
typedef
. Sie können es einfach wie folgt tunEs ist eine Stilfrage, ob Sie es vorziehen
typedef
. Ohne sie müssen Sie verwenden, wenn Sie auf den Aufzählungstyp verweisen möchtenenum strategy
. Damit kann man einfach sagenstrategy
.Beide Wege haben ihre Vor- und Nachteile. Der eine ist wortreicher, behält jedoch Typbezeichner im Tag-Namespace bei, wo sie nicht mit normalen Bezeichnern in Konflikt stehen (denken Sie an
struct stat
und diestat
Funktion: Diese stehen auch nicht in Konflikt), und wo Sie sofort sehen, dass es sich um einen Typ handelt. Der andere ist kürzer, bringt jedoch Typbezeichner in den normalen Namespace.quelle
enum
Schlüsselwort in beiden Zeilen verwendet wird.enum strategy { RANDOM, IMMEDIATE, SEARCH };
Wenn Sie dann eine Instanz dieser Aufzählung wünschen: `Aufzählungsstrategie myEnum;Sie versuchen
strategy
zweimal zu deklarieren , und deshalb wird der obige Fehler angezeigt. Folgendes funktioniert ohne Beschwerden (zusammengestellt mitgcc -ansi -pendantic -Wall
):Wenn anstelle der obigen Zeile die zweite Zeile geändert wurde in:
Anhand der Warnungen konnten Sie Ihren Fehler leicht erkennen:
Der Compiler hat also
strategy = IMMEDIATE
eine Deklaration einer Variablenstrategy
mit dem Standardtyp aufgerufenint
, aber es gab bereits eine vorherige Deklaration einer Variablen mit diesem Namen.Wenn Sie die Zuweisung jedoch in die
main()
Funktion einfügen, ist dies ein gültiger Code:quelle
Wenn du sagst
Sie erstellen eine einzelne Instanzvariable mit dem Namen "Strategie" einer namenlosen Aufzählung. Dies ist keine sehr nützliche Sache - Sie benötigen ein typedef:
quelle
Wie geschrieben, ist nichts falsch an Ihrem Code. Bist du sicher, dass du so etwas noch nicht gemacht hast?
Auf welche Zeilen verweisen die Fehlermeldungen? Wenn es heißt "vorherige Erklärung der 'Strategie' war hier", was ist "hier" und was zeigt es?
quelle
strategy = IMMEDIATE;
im Dateibereich getan . Eine Zuweisung kann nicht im Dateibereich außerhalb aller Funktionen erfolgen. Der Compiler versuchte also, das Beste aus dem Fehler herauszuholen und nahm an, dass er meinteint strategy = IMMEDIATE;
, zu welchem Zeitpunkt der Konflikt auftrat.@ThoAppelsin in seinem Kommentar zur gestellten Frage ist richtig. Das in der Frage veröffentlichte Code-Snippet ist gültig und fehlerfrei. Der Fehler, den Sie haben, muss auf eine andere fehlerhafte Syntax an einer anderen Stelle Ihrer c-Quelldatei zurückzuführen sein.
enum{a,b,c};
definiert drei symbolische Konstanten (a
,b
undc
) , die ganzen Zahlen mit Werten sind0
,1
und2
jeweils, aber wenn wir verwendenenum
es, weil wir über den spezifischen ganzzahligen Wert der Regel nicht kümmern, kümmern wir uns mehr über die Bedeutung der symbolischen Konstante Namen. Dies bedeutet, dass Sie Folgendes haben können:und dies wird ausgegeben
1
.Dies gilt auch:
und gibt das gleiche wie zuvor aus.
Wenn du das tust:
Sie werden einen Fehler haben, aber wenn Sie dies tun:
Sie werden keinen Fehler haben.
du kannst das:
und
aa
wird eine ganzzahlige Variable mit Wert sein0
. Sie können dies aber auch tun:und wird den gleichen Effekt haben (
aa
dh einint
mit0
Wert sein).Sie können dies auch tun:
und
aa
wirdint
mit Wert sein7
.Da Sie die Definition symbolischer Konstanten nicht mit der Verwendung von wiederholen können
enum
, wie ich bereits sagte, müssen Sie Tags verwenden, wenn Sieint
vars mit der Verwendung von deklarieren möchtenenum
:Die Verwendung
typedef
dient dazu, Sie davor zu schützen, jedes Malenum tag1
zu schreiben , um eine Variable zu definieren. Mit könnentypedef
Sie einfach eingebenTag1
:Sie können auch haben:
Das Letzte, was zu sagen ist, ist, dass es besser ist, Großbuchstaben zu verwenden, wenn wir über definierte symbolische Konstanten sprechen
enum
, zum Beispiel:anstatt
quelle
Es ist erwähnenswert, dass Sie in C ++ "enum" verwenden können, um einen neuen Typ zu definieren, ohne eine typedef-Anweisung zu benötigen.
Ich finde diesen Ansatz viel freundlicher.
[Bearbeiten - geklärter C ++ - Status - Ich hatte diesen ursprünglich und entfernte ihn dann!]
quelle
typedef
oder auchenum
in der Variablendeklaration angeben : enum Strategy {RANDOM, IMMEDIATE, SEARCH}; ... enum Strategy myStrategy = IMMEDIATE;enum Strategy
. Ich habe das gemacht, siehe unten.Es scheint eine Verwirrung über die Erklärung zu geben.
Wann
strategy
kommt vorher{RANDOM, IMMEDIATE, SEARCH}
wie im Folgenden,Sie erstellen einen neuen Typ mit dem Namen
enum strategy
. Wenn Sie die Variable deklarieren, müssen Sie sichenum strategy
selbst verwenden. Sie können nicht einfach verwendenstrategy
. Das Folgende ist also ungültig.Währenddessen gilt Folgendes
Wenn es danach
strategy
kommt{RANDOM, IMMEDIATE, SEARCH}
, erstellen Sie eine anonyme Aufzählung und deklarierenstrategy
diese als Variable dieses Typs.Jetzt können Sie so etwas tun
Sie können jedoch keine andere Variable vom Typ deklarieren,
enum {RANDOM, IMMEDIATE, SEARCH}
da Sie sie nie benannt haben. Das Folgende ist also ungültigSie können auch beide Definitionen kombinieren
Typedef
Wie bereits erwähnt, wird eine kürzere Variablendeklaration erstellt.Jetzt haben Sie dem Compiler mitgeteilt, dass dies
enum {RANDOM, IMMEDIATE, SEARCH}
synonym iststrategy
. So können Sie jetzt freistrategy
als Variablentyp verwenden. Sie müssen nichtenum strategy
mehr tippen . Folgendes ist jetzt gültigSie können Typedef auch mit dem Namen der Aufzählung kombinieren, um sie zu erhalten
Es gibt nicht viel Vorteil der Verwendung dieses Verfahrens abgesehen von der Tatsache , dass Sie jetzt verwenden können
strategy
undenum strategyName
austauschbar.quelle
typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy
odertypedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_type
. Hat das einen Vorteil gegenübertypedef enum {RANDOM, IMMEDIATE, SEARCH} strategy
? Würden Sie diese der Vollständigkeit halber zu Ihrer Antwort hinzufügen?Wenn Sie den Namen für die Aufzählung deklarieren, tritt kein Fehler auf.
Wenn nicht deklariert, müssen Sie Folgendes verwenden
typedef
:Es wird kein Fehler angezeigt ...
quelle
Meine bevorzugte und einzige gebrauchte Konstruktion war immer:
Ich glaube, dass dies Ihr Problem beseitigen wird, das Sie haben. Die Verwendung eines neuen Typs ist aus meiner Sicht die richtige Option.
quelle
Tarcs Antwort ist die beste.
Ein Großteil der Aufzählungsdiskussion ist ein roter Hering.
Vergleichen Sie dieses Code-Snippet: -
was gibt
mit diesem, der ohne Probleme kompiliert.
Die Variable
strategy
muss bei der Deklaration oder innerhalb einer Funktion usw. festgelegt werden. Sie können keine beliebige Software - insbesondere Zuweisungen - im globalen Bereich schreiben.Die Tatsache, dass er anstelle von int enum {RANDOM, IMMEDIATE, SEARCH} verwendet hat, ist nur insoweit relevant, als es Menschen verwirrt hat, die nicht darüber hinaus sehen können. Die Fehlermeldungen zur Neudefinition in der Frage zeigen, dass der Autor dies falsch gemacht hat.
Jetzt sollten Sie sehen können, warum das erste der folgenden Beispiele falsch ist und die anderen drei in Ordnung sind.
Beispiel 1. FALSCH!
Beispiel 2. RECHTS.
Beispiel 3. RECHTS.
Beispiel 4. RECHTS.
Wenn Sie ein funktionierendes Programm haben, sollten Sie nur in der Lage sein, diese Schnipsel in Ihr Programm einzufügen und zu sehen, dass einige kompilieren und andere nicht.
quelle
Ich habe es mit gcc versucht und bin auf meine Bedürfnisse gekommen. Ich war gezwungen, die letzte Alternative zu verwenden, um ohne Fehler zu kompilieren.
typedef enum state {a = 0, b = 1, c = 2} state ;
quelle
new
ist eine schlechte Wahl für Bezeichner in der C-Familie, da es sich um einen Operator in C ++ handelt.C.
Deklaration, die als vorläufige Definition einer vorzeichenbehafteten Ganzzahl
s
mit vollständigem Typ fungiert, und Deklaration, die als vorläufige Definition einer vorzeichenbehafteten Ganzzahlq
mit unvollständigem Typ im Bereich fungiert (die in den vollständigen Typ im Bereich aufgelöst wird, da die Typdefinition an einer beliebigen Stelle im Bereich vorhanden ist scope) (wie bei jeder vorläufigen Definition können die Bezeichnerq
unds
mit der unvollständigen oder vollständigen Version desselben Typsint
oderenum stuff
mehrmals neu deklariert werden, jedoch nur einmal im Bereich definiert werden, dh int q = 3; und können nur in einem Unterbereich neu definiert werden, und nur nach der Definition verwendbar). Außerdem können Sie den vollständigen Typ nurenum stuff
einmal im Bereich verwenden, da er als Typdefinition fungiert.Eine Definition des Compiler-Aufzählungstyps für
enum stuff
wird auch im Dateibereich (vor und nach verwendbar) sowie eine Vorwärts-Typdeklaration vorhanden sein (der Typenum stuff
kann mehrere Deklarationen enthalten, aber nur eine Definition / Vervollständigung im Bereich und kann in einem Unterbereich neu definiert werden). . Es fungiert auch als eine Compiler - Direktive zu ersetzena
mit rvalue0
,b
mit-4
,c
mit5
,d
mit-2
,e
mit-3
,f
mit-1
undg
mit-2
in dem aktuellen Bereich. Die Aufzählungskonstanten gelten jetzt nach der Definition bis zur nächsten Neudefinition in einer anderen Aufzählung, die sich nicht auf derselben Bereichsebene befinden kann.Der Tag - Namespace von ENUM, struct und union geteilt ist getrennt und muss vom Typ Schlüsselwort (Enum, struct oder union) vorangestellt werden , in C dh nach
enum a {a} b
,enum a c
verwendet werden muss , und nichta c
. Da der Tag-Namespace vom Bezeichner-Namespace getrennt ist,enum a {a} b
ist dies zulässig, jedochenum a {a, b} b
nicht, da sich die Konstanten im selben Namespace wie die Variablen-Bezeichner befinden, dem Bezeichner-Namespace.typedef enum a {a,b} b
ist ebenfalls nicht zulässig, da typedef-names Teil des Bezeichner-Namespace sind.Der Typ
enum bool
und die Konstanten folgen dem folgenden Muster in C:Dies kompiliert gut in C:
C ++
In C ++ können Aufzählungen einen Typ haben
In dieser Situation haben die Konstanten und der Bezeichner alle denselben Typ, bool, und es tritt ein Fehler auf, wenn eine Zahl nicht durch diesen Typ dargestellt werden kann. Vielleicht = 2, was kein Bool ist. Außerdem können True, False und Bool nicht in Kleinbuchstaben geschrieben werden, da sie sonst mit Sprachschlüsselwörtern in Konflikt geraten. Eine Aufzählung kann auch keinen Zeigertyp haben.
Die Regeln für Aufzählungen unterscheiden sich in C ++.
Aufzählungsvariablen in C ++ sind nicht mehr nur vorzeichenlose Ganzzahlen usw., sondern auch vom Aufzählungstyp und können nur Konstanten in der Aufzählung zugewiesen werden. Dies kann jedoch weggeworfen werden.
Aufzählungsklassen
enum struct
ist identisch mitenum class
Der Bereichsauflösungsoperator kann weiterhin für Aufzählungen ohne Gültigkeitsbereich verwendet werden.
Da w jedoch nicht als etwas anderes im Geltungsbereich definiert werden kann, gibt es keinen Unterschied zwischen
::w
und::a::w
quelle