Jak zdefiniować typ wyliczeniowy (wyliczenie) w C?

272

Nie jestem pewien, jaka jest właściwa składnia do używania znaków C. Mam następujący kod:

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

Ale to się nie kompiluje, z następującym błędem:

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

Co ja robię źle?

Lindelof
źródło
7
Pytanie od lat, prawdopodobnie nikt tego nie zobaczy; ale dlaczego powoduje to błąd? Powinien działać idealnie, o ile jest to kwestia, o ile wiem.
Utkan Gezer
2
@ Solver dlaczego ta składnia jest nieprawidłowa?
MCG
6
@MCQ, nekrowanie nekrozy: Składnia przedstawiona w pytaniu nie jest niepoprawna w C. Deklaruje, strategyże ma anonimowy wyliczony typ i przypisuje mu jedną z zadeklarowanych wartości tego typu. Co więcej, jeśli zawijam kod przedstawiony w trywialnej main()funkcji, to kompiluje się dla mnie dobrze, nawet bez ostrzeżenia, z gcc 4.4.7. Niektóre odpowiedzi sugerują to samo, choć nie w tak wielu słowach.
John Bollinger,
5
W większości odpowiedzi brakuje tego, że dwa wiersze kodu w pytaniu nie są tylko fragmentem kodu. To cały plik źródłowy. Jeśli te dwie linie są zawarte w treści funkcji, nie ma błędu. Jeśli pojawią się w zakresie pliku, poza deklaracją funkcji, otrzymasz błędy, o które OP pytał (plus kilka innych, gdy próbowałem). Podstawowym problemem jest to, że kompilator próbuje traktować strategy = IMMEDIATE;jako deklarację. Ma formę, która byłaby legalna w czasach poprzedzających ANSI C, ale we współczesnym C jest to nielegalne. Przydziały nie są dozwolone w zakresie plików.
Keith Thompson,
3
@ Solver: enum strategy { ... };definiuje wyliczony typ o nazwie enum strategy, gdzie strategyjest tag. enum { ... } strategy;definiuje anonimowy wyliczony typ (bez znacznika) i pojedynczy obiekt tego typu o nazwie strategy. Oba są całkowicie legalne; oznaczają tylko różne rzeczy.
Keith Thompson,

Odpowiedzi:

377

Zadeklarowanie zmiennej wyliczeniowej odbywa się w następujący sposób:

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

Możesz jednak użyć a, typedefaby skrócić deklaracje zmiennych, tak jak to:

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

Posiadanie konwencji nazewnictwa w celu rozróżnienia typów i zmiennych jest dobrym pomysłem:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
RichieHindle
źródło
1
Ale OP chciał zmiennej anonimowego typu wyliczeniowego
osvein
Nie mogłem po prostu wpisać, enum MyEnum {} myVar;a następnie użyć zmiennej myVarw następujący sposób:myVar = SOMEENUMCONSTANT;
Mushy,
451

Warto podkreślić, że nie trzebatypedef . Możesz to zrobić w następujący sposób

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

To pytanie w stylu, czy wolisz typedef. Bez niego, jeśli chcesz odwoływać się do typu wyliczenia, musisz użyć enum strategy. Dzięki niemu możesz po prostu powiedzieć strategy.

Oba sposoby mają swoje zalety i wady. Ten jest bardziej niewygodny, ale przechowuje identyfikatory typów w przestrzeni nazw znaczników, gdzie nie będą konfliktować ze zwykłymi identyfikatorami (pomyśl struct stati statfunkcja: te też nie powodują konfliktu) i gdzie natychmiast zobaczysz, że jest to typ. Drugi jest krótszy, ale wprowadza identyfikatory typów do zwykłej przestrzeni nazw.

Johannes Schaub - litb
źródło
6
To nie powinna być zaakceptowana odpowiedź, ponieważ jest zła. Nie możesz używać strategii enum {...}; w C - możesz i powinieneś to zrobić w C ++.
Jaśniejsze
19
@Clearer: Ten kod działa idealnie. Oto działający przykład: ideone.com/T0YV17 Pamiętaj, że używa enumsłowa kluczowego w obu liniach.
RichieHindle
Lub „typedef enum strategia {RANDOM, NATYCHMIAST, SZUKAJ} strategia_t;” a twórca używający wyliczenia może zastosować dowolną konwencję.
Andy Nugent,
działa to doskonale: enum strategy { RANDOM, IMMEDIATE, SEARCH }; wtedy, gdy chcesz mieć instancję tego wyliczenia: `enum strategia myEnum;
user3629249
2
@AndyNugent nie rób tego! * Typy t są zastrzeżone przez POSIX
osvein
58

Próbujesz zadeklarować strategydwa razy i dlatego otrzymujesz powyższy błąd. Poniższe działa bez żadnych skarg (z kompilacją 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;
}

Jeśli zamiast powyższego, druga linia została zmieniona na:

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

Z ostrzeżeń możesz łatwo zobaczyć swój błąd:

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

Tak więc kompilator wziął strategy = IMMEDIATEdeklarację zmiennej strategyo typie domyślnym int, ale była już poprzednia deklaracja zmiennej o tej nazwie.

Jeśli jednak umieścisz przypisanie w main()funkcji, będzie to poprawny kod:

#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
źródło
48

Kiedy powiesz

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

tworzysz zmienną o pojedynczej instancji, zwaną „strategią” bezimiennego wyliczenia. To nie jest bardzo przydatna rzecz - potrzebujesz typedef:

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

źródło
9
Dlaczego to nie jest przydatne? Jeśli nie dbam o nazwę typu, dlaczego mam ją podać? Jedyną rzeczą, którą zamierzaliśmy tutaj, było nazwać zmienną, więc można przypisać do niej nowe wartości.
MSalters
3
Powiedziałem, że to nie było BARDZO przydatne i nie wierzę, że jest. Z pewnością nie używam tego wzorca we własnym kodzie. YMMV.
3
@HorseSMith Wyliczenie bez nazwy nie jest bardzo przydatne, ponieważ nie można mieć żadnej innej zmiennej tego typu, parametru funkcji ani wartości zwracanej. Jeśli jedna zmienna jest wszystkim, czego potrzebujesz, to jest w porządku.
Bob Stein,
3
Ktoś, kto nie używa anonimowych wyliczeń, nie udowodni, że nie ma pożytku. Nie potrzebujesz typedef. Niektóre wytyczne kodu (kernel.org/doc/Documentation/CodingStyle) nawet je odradzają.
martinkunev,
2
Ta odpowiedź TAKŻE wprowadza w błąd. Odpowiedź Tarca jest tutaj jedyną właściwą.
nightpool
13

Jak napisano, nie ma nic złego w kodzie. Jesteś pewien, że nie zrobiłeś czegoś takiego

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

Jakie linie wskazują komunikaty o błędach? Kiedy mówi „poprzednia deklaracja„ strategii ”była tutaj”, co jest „tutaj” i co to pokazuje?

John Bode
źródło
6
Prawdopodobnie zrobił to strategy = IMMEDIATE;w zakresie plików. Przypisanie nie może nastąpić w zakresie plików poza wszystkimi funkcjami. Tak więc kompilator próbował zrobić wszystko, co w jego mocy, i przyjął, że miał int strategy = IMMEDIATE;na myśli , w którym momencie nastąpił konflikt.
Johannes Schaub - litb
2
To najlepsza odpowiedź, w innych odpowiedziach jest tak mętne zamieszanie, że bolesne.
zrelaksuj się
12

@ThoAppelsin w swoim komentarzu do zadanego pytania ma rację. Fragment kodu opublikowany w pytaniu jest prawidłowy i bez błędów. Wystąpił błąd, ponieważ inna zła składnia w innym miejscu pliku źródłowego c. enum{a,b,c};definiuje trzy stałe symboliczne ( a, bi c), które są liczbami całkowitymi z wartościami 0, 1i 2odpowiednio, ale kiedy enumgo używamy , to dlatego, że zwykle nie dbamy o konkretną wartość całkowitą, bardziej zależy nam na znaczeniu stałej symbolicznej. Oznacza to, że możesz mieć to:

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

i to da wynik 1.

To również będzie ważne:

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

i wyświetli takie same jak poprzednio.

Jeśli to zrobisz:

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

wystąpi błąd, ale jeśli to zrobisz:

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

nie wystąpi żaden błąd.

możesz to zrobić:

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

i aabędzie zmienną całkowitą o wartości 0. ale możesz również to zrobić:

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

i mieć ten sam efekt, (to znaczy, aabędąc intz 0wartości).

możesz również to zrobić:

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

i aabędzie intz wartością 7.

ponieważ nie można powtórzyć stałej symbolicznej przy użyciu enum, jak już powiedziałem, musisz użyć tagów, jeśli chcesz zadeklarować intzmienne przy użyciu enum:

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

jego użycie typedefma uchronić cię przed pisaniem za każdym razem, enum tag1aby zdefiniować zmienną. Dzięki typedefmożesz po prostu wpisać Tag1:

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

Możesz również mieć:

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

Ostatnią rzeczą do powiedzenia jest to, że skoro mówimy o zdefiniowanych stałych symbolicznych, lepiej jest używać liter pisanych wielkimi literami enum, np.

enum {A,B,C};

zamiast

enum {a,b,c};
roggc
źródło
10

Warto wspomnieć, że w C ++ można użyć „enum” do zdefiniowania nowego typu bez potrzeby używania instrukcji typedef.

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

Uważam to podejście za bardziej przyjazne.

[edytuj - wyjaśniono status C ++ - miałem to pierwotnie, a następnie usunąłem!]

Roddy
źródło
Tak, nigdy nie powinieneś używać typedef z wyliczeniami (lub strukturami, związkami itp.) W C ++.
17
To pytanie dotyczy C, a nie C ++. W C powyższy kod jest nieprawidłowy - musisz albo użyć typedef, albo też podać enumw zmiennej deklaracji: enum Strategy {RANDOM, NATYCHMIAST, SZUKAJ}; ... strategia enum myStrategy = NATYCHMIAST;
Pavel Minaev
@pavel - my bad. Początkowo miałem „w C ++”, a potem przeprowadziłem badania, które wydawały się temu zaprzeczać.
Roddy
@Pavel Myślę, że powinna to być osobna odpowiedź opisująca zalety korzystania enum Strategy. Zrobiłem to, patrz poniżej.
Johannes Schaub - litb
8

Wydaje się, że istnieje zamieszanie co do deklaracji.

Kiedy strategynastąpi wcześniej, {RANDOM, IMMEDIATE, SEARCH}jak poniżej,

enum strategy {RANDOM, IMMEDIATE, SEARCH};

tworzysz nowy typ o nazwie enum strategy. Jednak deklarując zmienną, musisz użyć jej enum strategysamej. Nie możesz tak po prostu użyć strategy. Zatem poniższe informacje są nieprawidłowe.

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

Chociaż poniższe informacje są prawidłowe

enum strategy {RANDOM, IMMEDIATE, SEARCH};

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

Kiedy strategyprzyjdzie później {RANDOM, IMMEDIATE, SEARCH}, tworzysz anonimowy wyliczenie, a następnie deklarujesz, strategyże jest zmienną tego typu.

Teraz możesz zrobić coś takiego

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

Nie można jednak zadeklarować żadnej innej zmiennej typu, enum {RANDOM, IMMEDIATE, SEARCH}ponieważ nigdy jej nie nadano. Zatem poniższe informacje są nieprawidłowe

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

Możesz także połączyć obie definicje

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

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

Typedef jak wspomniano wcześniej, służy do tworzenia krótszej deklaracji zmiennej.

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;

Teraz powiedziałeś kompilatorowi, który enum {RANDOM, IMMEDIATE, SEARCH}jest synonimem strategy. Teraz możesz swobodnie używać strategyjako typu zmiennej. Nie musisz enum strategyjuż pisać . Następujące informacje są teraz aktualne

strategy x = RANDOM;

Możesz także połączyć Typedef z nazwą wyliczenia, aby uzyskać

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

Korzystanie z tej metody nie ma wiele zalet poza tym, że można jej teraz używać strategyi enum strategyNamezamieniać.

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

enum strategyName a = RANDOM;
strategy b = SEARCH;
Dezorientować
źródło
1
Świetna odpowiedź. Natknąłem się również na definicje enum napisane w ten sposób: typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategylub typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_type. Czy ma to jakąś przewagę typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy? Czy chciałbyś rozważyć dodanie ich do swojej odpowiedzi?
tjalling
Tak. Zmodyfikowałem swoją odpowiedź. Zgodnie z moją wiedzą w ogóle nie ma żadnej istotnej przewagi.
Mylić
2
Świetnie, twoja odpowiedź obejmuje teraz wszystko, dzięki. Szkoda, że ​​jest tak daleko na liście odpowiedzi, nie tylko dlatego, że wyraźnie odnosi się do pierwotnego pytania, z odpowiednim wyjaśnieniem.
tjalling
2

Jeśli podasz nazwę wyliczenia, nie wystąpi błąd.

Jeśli nie zostało zadeklarowane, musisz użyć typedef:

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

Nie wyświetli błędu ...

Peter Mortensen
źródło
2

Moją ulubioną i używaną konstrukcją zawsze była:

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

Wierzę, że to usunie twój problem. Używanie nowego typu jest z mojego punktu widzenia właściwą opcją.

Sany
źródło
1

Odpowiedź Tarca jest najlepsza.

Znaczna część dyskusji wyliczeniowej to czerwony śledź.

Porównaj ten fragment kodu: -

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

co daje

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

z tym, który kompiluje się bez problemu.

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

Zmienna strategy musi być ustawiona w deklaracji lub wewnątrz funkcji itp. Nie można pisać dowolnego oprogramowania - w szczególności przypisań - w zakresie globalnym.

Fakt, że użył enum {RANDOM, NATYCHMIAST, SZUKAJ} zamiast int jest istotny tylko w takim stopniu, w jakim wprawił w zakłopotanie ludzi, którzy nie widzą poza tym. Komunikaty o błędach redefinicji w pytaniu pokazują, że autor postąpił źle.

Więc teraz powinieneś zobaczyć, dlaczego pierwszy z poniższych przykładów jest nieprawidłowy, a pozostałe trzy są w porządku.

Przykład 1. ŹLE!

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

Przykład 2. PRAWO.

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

Przykład 3. PRAWO.

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

Przykład 4. PRAWO.

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

Jeśli masz działający program, powinieneś po prostu móc wkleić te fragmenty do swojego programu i zobaczyć, że niektóre kompilują, a inne nie.

Ivan
źródło
0

Próbowałem z gcc i wymyśliłem dla mojej potrzeby byłem zmuszony użyć ostatniej alternatywy, aby skompilować bez błędu.

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

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
źródło
newjest złym wyborem identyfikatorów w rodzinie C, ponieważ jest operatorem w C ++.
jww
0

do

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

Deklaracja, która działa jako wstępna definicja podpisanej liczby całkowitej sz pełnym typem i deklaracja, która działa jako wstępna definicja podpisanej liczby całkowitej qz niekompletnym typem w zakresie (który rozwiązuje się do pełnego typu w zakresie, ponieważ definicja typu znajduje się w dowolnym miejscu w zakres) (jak każda wstępna definicja, identyfikatory qi smogą być ponownie zadeklarowane z niekompletną lub pełną wersją tego samego typu intlub enum stuffwiele razy, ale tylko raz zdefiniowane w zakresie, tj. int q = 3; i mogą być ponownie zdefiniowane tylko w podzakresie, oraz możliwe do użycia tylko po definicji). Możesz także użyć pełnego typu enum stuffraz w zakresie, ponieważ działa on jak definicja typu.

Definicja typu wyliczenia kompilatora dla enum stuffjest również obecna w zakresie pliku (użyteczne przed i poniżej), a także w deklaracji typu forward (typ enum stuffmoże mieć wiele deklaracji, ale tylko jedną definicję / uzupełnienie w zakresie i może być przedefiniowany w podskopie) . Działa również jako dyrektywy kompilatora do zastąpienia az rvalue 0, bz -4, cz 5, dz -2, ez -3, fz -1, a gze -2w obecnym zakresie. Stałe wyliczenia obowiązują teraz po definicji do następnej redefinicji w innym wyliczeniu, które nie może być na tym samym poziomie zakresu.

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 

Przestrzeń nazw znaczników współdzielona przez enum, struct i union jest osobna i musi być poprzedzona słowem kluczowym type (enum, struct lub union) w C, tzn. Po enum a {a} b, enum a cmusi być używana, a nie a c. Ponieważ przestrzeń nazw znacznika jest oddzielna od przestrzeni nazw identyfikatora, enum a {a} bjest dozwolona, ​​ale enum a {a, b} bnie dlatego, że stałe znajdują się w tej samej przestrzeni nazw, co identyfikatory zmiennych, przestrzeń nazw identyfikatora. typedef enum a {a,b} bjest również niedozwolone, ponieważ typedef-names są częścią przestrzeni nazw identyfikatora.

Typ enum booli stałe są zgodne z następującym wzorcem w 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 |
+-----------+-----+---------------+------+

Kompiluje się dobrze w 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 ++

W C ++ wyliczenia mogą mieć typ

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

W tej sytuacji wszystkie stałe i identyfikator mają ten sam typ, bool, i wystąpi błąd, jeśli liczba nie może być reprezentowana przez ten typ. Może = 2, co nie jest boolem. Również True, False i Bool nie mogą być pisane małymi literami, w przeciwnym razie będą kolidować ze słowami kluczowymi języka. Wyliczenie również nie może mieć typu wskaźnika.

Zasady wyliczania są różne w 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;
}

Zmienne wyliczające w C ++ nie są już tylko liczbami całkowitymi bez znaku itp., Są również typu wyliczeniowego i można im przypisywać tylko stałe w wyliczeniu. Można to jednak odrzucić.

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

Klasy enum

enum struct jest identyczny z 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
}

Operator rozdzielczości zakresu nadal może być używany do wyliczeń nieposiadających zasięgu.

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

Ale ponieważ w nie można zdefiniować jako czegoś innego w zakresie, nie ma różnicy między ::wi::a::w

Lewis Kelsey
źródło