Wie definiere ich einen Aufzählungstyp (Aufzählung) in C?

272

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?

Lindelof
quelle
7
Jahre alte Frage, wahrscheinlich wird das niemand sehen; aber warum gibt dies einen Fehler? Soweit ich weiß, sollte es einwandfrei funktionieren.
Utkan Gezer
2
@ Solver warum ist diese Syntax falsch?
MCG
6
@MCQ, necroing the necro'd necro: Die in der Frage dargestellte Syntax ist in C nicht falsch. Sie deklariert strategyeinen anonymen Aufzählungstyp und weist ihr einen der deklarierten Werte dieses Typs zu. Wenn ich den Code in eine ansonsten triviale main()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.
John Bollinger
5
Den meisten Antworten fehlt die Tatsache, dass die beiden Codezeilen in der Frage nicht nur ein Ausschnitt sind. Sie sind die gesamte Quelldatei. Wenn diese beiden Zeilen im Hauptteil einer Funktion enthalten sind, liegt kein Fehler vor. Wenn sie außerhalb einer Funktionsdeklaration im Dateibereich angezeigt werden, werden die Fehler angezeigt, nach denen das OP gefragt hat (plus einige andere, als ich es ausprobiert habe). Das grundlegende Problem ist, dass der Compiler versucht, 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.
Keith Thompson
3
@Solver: Definiert enum strategy { ... };einen Aufzählungstyp mit dem Namen enum strategy, wobei strategysich das Tag befindet. enum { ... } strategy;definiert einen anonymen Aufzählungstyp (kein Tag) und ein einzelnes Objekt dieses Typs mit dem Namen strategy. Beide sind vollkommen legal; Sie bedeuten nur verschiedene Dinge.
Keith Thompson

Antworten:

377

Das Deklarieren einer Enum-Variablen erfolgt folgendermaßen:

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

Sie können jedoch a verwenden typedef, um die Variablendeklarationen wie folgt zu verkürzen:

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

Eine Namenskonvention zur Unterscheidung zwischen Typen und Variablen ist eine gute Idee:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
RichieHindle
quelle
1
Aber OP wollte eine Variable eines anonymen Aufzählungstyps
Osvein
Könnte ich nicht einfach enum MyEnum {} myVar;die Variable myVarmyVar = SOMEENUMCONSTANT;
eingeben
451

Es ist erwähnenswert, dass Sie nicht brauchen ein typedef. Sie können es einfach wie folgt tun

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

Es ist eine Stilfrage, ob Sie es vorziehen typedef. Ohne sie müssen Sie verwenden, wenn Sie auf den Aufzählungstyp verweisen möchten enum strategy. Damit kann man einfach sagen strategy.

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 statund die statFunktion: 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.

Johannes Schaub - litb
quelle
6
Es sollte nicht die akzeptierte Antwort sein, weil es falsch ist. Sie können die Aufzählungsstrategie {...} nicht verwenden. in C - Sie können und sollten dies jedoch in C ++ tun.
Klarer
19
@Clearer: Dieser Code funktioniert perfekt. Hier ist ein funktionierendes Beispiel: ideone.com/T0YV17 Beachten Sie, dass das enumSchlüsselwort in beiden Zeilen verwendet wird.
RichieHindle
Oder "typedef enum strategie {RANDOM, IMMEDIATE, SEARCH} strategie_t;" und der Entwickler, der die Aufzählung verwendet, kann jede gewünschte Konvention verwenden.
Andy Nugent
Dies funktioniert hervorragend: enum strategy { RANDOM, IMMEDIATE, SEARCH }; Wenn Sie dann eine Instanz dieser Aufzählung wünschen: `Aufzählungsstrategie myEnum;
user3629249
2
@AndyNugent mach das nicht! * _t Typen sind von POSIX
osvein
58

Sie versuchen strategyzweimal zu deklarieren , und deshalb wird der obige Fehler angezeigt. Folgendes funktioniert ohne Beschwerden (zusammengestellt mit 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;
}

Wenn anstelle der obigen Zeile die zweite Zeile geändert wurde in:

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

Anhand der Warnungen konnten Sie Ihren Fehler leicht erkennen:

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

Der Compiler hat also strategy = IMMEDIATEeine Deklaration einer Variablen strategymit dem Standardtyp aufgerufen int, 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:

#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
quelle
48

Wenn du sagst

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

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:

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

quelle
9
Warum ist das nicht sinnvoll? Wenn mir der Name des Typs egal ist, warum sollte ich ihm einen geben? Hier sollte nur die Variable benannt werden, damit ihr neue Werte zugewiesen werden können.
MSalters
3
Ich sagte, es sei nicht sehr nützlich, und ich glaube nicht, dass es so ist. Natürlich verwende ich dieses Muster nicht in meinem eigenen Code. YMMV.
3
@HorseSMith Eine unbenannte Aufzählung ist nicht sehr nützlich, da Sie keine andere Variable dieses Typs, Funktionsparameters oder Rückgabewerts haben können. Wenn die eine Variable alles ist, was Sie brauchen, ist es in Ordnung.
Bob Stein
3
Jemand, der keine anonymen Aufzählungen verwendet, beweist nicht, dass er keine Verwendung hat. Sie brauchen kein typedef. Einige Code-Richtlinien (kernel.org/doc/Documentation/CodingStyle) raten sogar davon ab.
Martinkunev
2
Diese Antwort ist auch irreführend. Tarcs Antwort ist hier die einzig richtige.
Nachtpool
13

Wie geschrieben, ist nichts falsch an Ihrem Code. Bist du sicher, dass du so etwas noch nicht gemacht hast?

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

Auf welche Zeilen verweisen die Fehlermeldungen? Wenn es heißt "vorherige Erklärung der 'Strategie' war hier", was ist "hier" und was zeigt es?

John Bode
quelle
6
Er hat es wahrscheinlich 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 meinte int strategy = IMMEDIATE;, zu welchem ​​Zeitpunkt der Konflikt auftrat.
Johannes Schaub - litb
2
Dies ist die beste Antwort, es gibt so viel Verwirrung in den anderen Antworten, dass es schmerzhaft ist.
Entspannen Sie am
12

@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, bund c) , die ganzen Zahlen mit Werten sind 0, 1und 2jeweils, aber wenn wir verwenden enumes, 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:

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

und dies wird ausgegeben 1.

Dies gilt auch:

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

und gibt das gleiche wie zuvor aus.

Wenn du das tust:

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

Sie werden einen Fehler haben, aber wenn Sie dies tun:

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

Sie werden keinen Fehler haben.

du kannst das:

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

und aawird eine ganzzahlige Variable mit Wert sein 0. Sie können dies aber auch tun:

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

und wird den gleichen Effekt haben ( aadh ein intmit 0Wert sein).

Sie können dies auch tun:

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

und aawird intmit Wert sein 7.

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 Sie intvars mit der Verwendung von deklarieren möchten enum:

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

Die Verwendung typedefdient dazu, Sie davor zu schützen, jedes Mal enum tag1zu schreiben , um eine Variable zu definieren. Mit können typedefSie einfach eingeben Tag1:

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

Sie können auch haben:

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

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:

enum {A,B,C};

anstatt

enum {a,b,c};
roggc
quelle
10

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.

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

Ich finde diesen Ansatz viel freundlicher.

[Bearbeiten - geklärter C ++ - Status - Ich hatte diesen ursprünglich und entfernte ihn dann!]

Roddy
quelle
Ja, Sie sollten typedef niemals mit Aufzählungen (oder Strukturen, Vereinigungen usw.) in C ++ verwenden.
17
Diese Frage ist für C, nicht für C ++. In C ist der obige Code ungültig - Sie müssen ihn entweder verwenden typedefoder auch enumin der Variablendeklaration angeben : enum Strategy {RANDOM, IMMEDIATE, SEARCH}; ... enum Strategy myStrategy = IMMEDIATE;
Pavel Minaev
@pavel - mein schlechtes. Ich hatte ursprünglich "in C ++" und dann einige Nachforschungen angestellt, die dem zu widersprechen schienen.
Roddy
@Pavel Ich denke, es sollte eine separate Antwort sein, die die Vorteile der Verwendung beschreibt enum Strategy. Ich habe das gemacht, siehe unten.
Johannes Schaub - litb
8

Es scheint eine Verwirrung über die Erklärung zu geben.

Wann strategykommt vorher {RANDOM, IMMEDIATE, SEARCH}wie im Folgenden,

enum strategy {RANDOM, IMMEDIATE, SEARCH};

Sie erstellen einen neuen Typ mit dem Namen enum strategy. Wenn Sie die Variable deklarieren, müssen Sie sich enum strategyselbst verwenden. Sie können nicht einfach verwenden strategy. Das Folgende ist also ungültig.

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

Währenddessen gilt Folgendes

enum strategy {RANDOM, IMMEDIATE, SEARCH};

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

Wenn es danach strategykommt {RANDOM, IMMEDIATE, SEARCH}, erstellen Sie eine anonyme Aufzählung und deklarieren strategydiese als Variable dieses Typs.

Jetzt können Sie so etwas tun

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

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ültig

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

Sie können auch beide Definitionen kombinieren

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

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

Typedef Wie bereits erwähnt, wird eine kürzere Variablendeklaration erstellt.

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;

Jetzt haben Sie dem Compiler mitgeteilt, dass dies enum {RANDOM, IMMEDIATE, SEARCH}synonym ist strategy. So können Sie jetzt frei strategyals Variablentyp verwenden. Sie müssen nicht enum strategymehr tippen . Folgendes ist jetzt gültig

strategy x = RANDOM;

Sie können Typedef auch mit dem Namen der Aufzählung kombinieren, um sie zu erhalten

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

Es gibt nicht viel Vorteil der Verwendung dieses Verfahrens abgesehen von der Tatsache , dass Sie jetzt verwenden können strategyund enum strategyNameaustauschbar.

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

enum strategyName a = RANDOM;
strategy b = SEARCH;
Verwechseln
quelle
1
Gute Antwort. Ich bin auch auf Enum-Definitionen gestoßen, die so geschrieben sind: typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategyoder typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_type. Hat das einen Vorteil gegenüber typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy? Würden Sie diese der Vollständigkeit halber zu Ihrer Antwort hinzufügen?
Tjalling
Ja. Ich habe meine Antwort geändert. Meines Wissens gibt es im Allgemeinen keinen großen Vorteil.
Verwirren Sie den
2
Großartig, Ihre Antwort deckt jetzt alles ab, danke. Schade, dass es so weit unten in der Liste der Antworten steht, nicht zuletzt, weil es die ursprüngliche Frage explizit mit der richtigen Erklärung anspricht.
Tjalling
2

Wenn Sie den Namen für die Aufzählung deklarieren, tritt kein Fehler auf.

Wenn nicht deklariert, müssen Sie Folgendes verwenden typedef:

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

Es wird kein Fehler angezeigt ...

Peter Mortensen
quelle
2

Meine bevorzugte und einzige gebrauchte Konstruktion war immer:

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

Ich glaube, dass dies Ihr Problem beseitigen wird, das Sie haben. Die Verwendung eines neuen Typs ist aus meiner Sicht die richtige Option.

Sany
quelle
1

Tarcs Antwort ist die beste.

Ein Großteil der Aufzählungsdiskussion ist ein roter Hering.

Vergleichen Sie dieses Code-Snippet: -

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

was gibt

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

mit diesem, der ohne Probleme kompiliert.

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

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!

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

Beispiel 2. RECHTS.

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

Beispiel 3. RECHTS.

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

Beispiel 4. RECHTS.

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

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.

Ivan
quelle
0

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 ;

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
quelle
newist eine schlechte Wahl für Bezeichner in der C-Familie, da es sich um einen Operator in C ++ handelt.
JWW
0

C.

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

Deklaration, die als vorläufige Definition einer vorzeichenbehafteten Ganzzahl smit vollständigem Typ fungiert, und Deklaration, die als vorläufige Definition einer vorzeichenbehafteten Ganzzahl qmit 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 Bezeichner qund smit der unvollständigen oder vollständigen Version desselben Typs intoder enum stuffmehrmals 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 nur enum stuffeinmal im Bereich verwenden, da er als Typdefinition fungiert.

Eine Definition des Compiler-Aufzählungstyps für enum stuffwird auch im Dateibereich (vor und nach verwendbar) sowie eine Vorwärts-Typdeklaration vorhanden sein (der Typ enum stuffkann 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 ersetzen amit rvalue 0, bmit -4, cmit 5, dmit -2, emit -3, fmit -1und gmit -2in 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.

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 

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 cverwendet werden muss , und nicht a c. Da der Tag-Namespace vom Bezeichner-Namespace getrennt ist, enum a {a} bist dies zulässig, jedoch enum a {a, b} bnicht, da sich die Konstanten im selben Namespace wie die Variablen-Bezeichner befinden, dem Bezeichner-Namespace.typedef enum a {a,b} bist ebenfalls nicht zulässig, da typedef-names Teil des Bezeichner-Namespace sind.

Der Typ enum boolund die Konstanten folgen dem folgenden Muster in 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 |
+-----------+-----+---------------+------+

Dies kompiliert gut in 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 ++

In C ++ können Aufzählungen einen Typ haben

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

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 ++.

#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;
}

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.

#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
}

Aufzählungsklassen

enum struct ist identisch mit 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
}

Der Bereichsauflösungsoperator kann weiterhin für Aufzählungen ohne Gültigkeitsbereich verwendet werden.

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

Da w jedoch nicht als etwas anderes im Geltungsbereich definiert werden kann, gibt es keinen Unterschied zwischen ::wund::a::w

Lewis Kelsey
quelle