Jak zdefiniować typ enumerated (enum) w C?
Nie jestem pewien, jaka jest właściwa składnia używania enum C. Mam następujący kod:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
Ale to nie kompiluje się, z następującym błędem:
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
Co robię źle? 13 answers
Deklarowanie zmiennej enum odbywa się w następujący sposób:
enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy my_strategy = IMMEDIATE;
Można jednak użyć typedef
, aby skrócić deklaracje zmiennych, w następujący sposób:
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy my_strategy = IMMEDIATE;
Posiadanie konwencji nazewnictwa do rozróżniania typów i zmiennych jest dobrym pomysłem:
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-07 15:34:57
Warto zaznaczyć, że nie potrzebujesz a typedef
. Możesz to zrobić w następujący sposób
enum strategy { RANDOM, IMMEDIATE, SEARCH };
enum strategy my_strategy = IMMEDIATE;
To pytanie o styl, czy wolisz typedef
. Bez niego, jeśli chcesz odwołać się do typu wyliczenia, musisz użyć enum strategy
. Z nim, można po prostu powiedzieć strategy
.
struct stat
i stat
funkcja: te też nie kolidują), i gdzie od razu widać, że jest to typ. Drugi jest krótszy, ale wprowadza identyfikatory typu do zwykłej przestrzeni nazw.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 16:12:55
Próbujesz zadeklarować strategy
dwa razy i dlatego otrzymujesz powyższy błąd. Poniższe prace bez żadnych reklamacji (zestawione z gcc -ansi -pedantic -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ń łatwo widać 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
Więc kompilator wziął {[6] } za deklarację zmiennej o nazwie strategy
z domyślnym typem int
, ale była już poprzednia deklaracja zmiennej o tym nazwisko.
Jeśli jednak umieścisz przypisanie w funkcji main()
, 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-16 09:28:02
Kiedy mówisz
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
Tworzysz pojedynczą zmienną instancji, zwaną 'strategy' bezimiennego enum. To nie jest bardzo przydatna rzecz do zrobienia - potrzebujesz typedef:
typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType;
StrategyType strategy = IMMEDIATE;
Jak napisano, nie ma nic złego w Twoim kodzie. Czy na pewno nie zrobiłeś czegoś takiego jak
int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
Na jakie linie wskazują komunikaty o błędach? Kiedy mówi "poprzednia deklaracja' strategii 'była tutaj", co jest "tutaj" i co pokazuje?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 15:38:16
Warto wspomnieć, że w C++ można użyć "enum" do zdefiniowania nowego typu bez konieczności użycia instrukcji typedef.
enum Strategy {RANDOM, IMMEDIATE, SEARCH};
...
Strategy myStrategy = IMMEDIATE;
Uważam to podejście za bardziej przyjazne.
[edytuj-poprawiłem C++ status-miałem to w oryginale, potem usunąłem!]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 09:16:03
@ThoAppelsin w komentarzu do pytania zamieszczonego ma rację. Fragment kodu zamieszczony w pytaniu jest poprawny i bez błędów. Błąd, który masz, musi być ponieważ inna zła składnia w dowolnym innym miejscu pliku źródłowego c. enum{a,b,c};
definiuje trzy stałe symboliczne (a
, b
i c
), które są liczbami całkowitymi o wartościach 0
,1
i odpowiednio 2
, Ale kiedy używamy enum
to dlatego, że zwykle nie zależy nam na konkretnej wartości całkowitej, bardziej zależy nam na znaczeniu symboliczna stała nazwa.
Oznacza to, że możesz mieć to:
#include <stdio.h>
enum {a,b,c};
int main(){
printf("%d\n",b);
return 0;
}
I to wyjdzie 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 to samo co wcześniej.
Jeśli to zrobisz:
enum {a,b,c};
enum {a,b,c};
Będziesz miał błąd, ale jeśli to zrobisz:
enum alfa{a,b,c};
enum alfa;
Nie będziesz miał żadnego błędu.
Możesz to zrobić:
enum {a,b,c};
int aa=a;
I {[21] } będą zmienną całkowitą o wartości 0
. ale można też zrobić to:
enum {a,b,c} aa= a;
I będzie miał ten sam efekt (tj. aa
będąc int
Z 0
wartością).
enum {a,b,c} aa= a;
aa= 7;
I aa
będą int
z wartością 7
.
Ponieważ nie możesz powtarzać definicji stałej symbolicznej za pomocą enum
, Jak już wcześniej powiedziałem, musisz użyć tagów, jeśli chcesz zadeklarować int
vars za pomocą enum
:
enum tag1 {a,b,c};
enum tag1 var1= a;
enum tag1 var2= b;
Użycie typedef
ma zabezpieczyć Cię przed pisaniem za każdym razem enum tag1
do zdefiniuj zmienną. Z typedef
możesz po prostu wpisać Tag1
:
typedef enum {a,b,c} Tag1;
Tag1 var1= a;
Tag1 var2= b;
Możesz też mieć:
typedef enum tag1{a,b,c}Tag1;
Tag1 var1= a;
enum tag1 var2= b;
Ostatnią rzeczą do powiedzenia jest to, że ponieważ mówimy o zdefiniowanych stałych symbolicznych, lepiej jest używać wielkich liter przy użyciu enum
, to jest na przykład:
enum {A,B,C};
Zamiast
enum {a,b,c};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-13 07:40:39
Wydaje się być zamieszanie co do deklaracji.
Kiedy strategy
jest przed {RANDOM, IMMEDIATE, SEARCH}
jak w poniższym,
enum strategy {RANDOM, IMMEDIATE, SEARCH};
Tworzysz nowy typ o nazwie enum strategy
. Jednakże, deklarując zmienną, musisz użyć samej enum strategy
. Nie możesz po prostu użyć strategy
. Tak więc poniższy tekst jest nieważny.
enum strategy {RANDOM, IMMEDIATE, SEARCH};
strategy a;
While, the following is valid
enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy queen = RANDOM;
enum strategy king = SEARCH;
enum strategy pawn[100];
Kiedy strategy
przychodzi po {RANDOM, IMMEDIATE, SEARCH}
, tworzysz anonimowe enum, a następnie deklarujesz strategy
jako zmienna tego typu.
Więc teraz możesz zrobić coś takiego
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = RANDOM;
Nie możesz jednak zadeklarować żadnej innej zmiennej typu enum {RANDOM, IMMEDIATE, SEARCH}
, ponieważ nigdy jej nie nazwałeś. Tak więc poniższy tekst jest nieprawidłowy
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategy a = RANDOM;
Możesz też połączyć obie definicje
enum strategy {RANDOM, IMMEDIATE, SEARCH} a, b;
a = RANDOM;
b = SEARCH;
enum strategy c = IMMEDIATE;
Typedef
Jak wspomniano wcześniej jest używany do tworzenia krótszej deklaracji zmiennej.
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
Teraz powiedziałeś kompilatorowi, że enum {RANDOM, IMMEDIATE, SEARCH}
jest synonimem strategy
. Więc teraz możesz swobodnie korzystać strategy
jako typ zmiennej. Nie musisz już pisać enum strategy
. Poniżej obowiązuje
strategy x = RANDOM;
Możesz również połączyć Typedef wraz z nazwą enum, aby uzyskać
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
Nie ma dużej korzyści z używania tej metody poza faktem, że można teraz używać strategy
i enum strategyName
zamiennie.
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategyName a = RANDOM;
strategy b = SEARCH;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-15 08:54:27
Jeśli zadeklarujesz nazwę do wyliczenia, nie wystąpi żaden błąd.
Jeśli nie jest zadeklarowana, musisz użyć typedef
:
enum enum_name {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
Nie wyświetli błędu...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 20:14:15
Moja ulubiona i tylko używana konstrukcja zawsze była:
typedef enum MyBestEnum
{
/* good enough */
GOOD = 0,
/* even better */
BETTER,
/* divine */
BEST
};
Wierzę, że to rozwiąże twój problem. Używanie nowego typu jest z mojego punktu widzenia dobrą opcją.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-31 08:41:45
Odpowiedź Tarca jest najlepsza.
Większość dyskusji enum 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ć dowolnych programów-w szczególności zadań-w zasięgu globalnym.
Fakt, że użył enum {RANDOM, IMMEDIATE, SEARCH} zamiast int jest tylko istotne do tego stopnia, że zdezorientował ludzi, którzy nie mogą zobaczyć poza nim. Komunikaty o błędach redefinicji w pytaniu pokazują, że to jest to, co autor zrobił źle.
Więc teraz powinieneś być w stanie zrozumieć, dlaczego pierwszy z poniższego przykładu jest zły, 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. Racja.
enum {RANDOM, IMMEDIATE, SEARCH} strategy = IMMEDIATE;
void some_function(void)
{
}
Przykład 3. Racja.
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
void some_function(void)
{
strategy = IMMEDIATE;
}
Przykład 4. Racja.
void some_function(void)
{
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
}
Jeśli masz program roboczy, powinieneś być w stanie wkleić te fragmenty do programu i zobaczyć, że niektóre kompilują, a niektóre nie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-02 08:29:15
Próbowałem z gcc i wymyślić dla mojej potrzeby byłem zmuszony użyć ostatniej alternatywy, aby skompilować się bez błędu.
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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-07 21:31:06
C
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 s
z typem kompletnym i deklaracja, która działa jako wstępna definicja podpisanej liczby całkowitej q
z typem niekompletnym w zakresie (która rozwiązuje się do typu pełnego w zakresie, ponieważ definicja typu jest obecna w dowolnym miejscu zakresu) (podobnie jak każda wstępna definicja, identyfikatory q
i s
mogą być ponownie zadeklarowane z niepełną lub pełną wersją tego samego typu int
lub enum stuff
wiele razy, ale tylko raz zdefiniowany w zakresie, tj. int q = 3; i może być ponownie zdefiniowany tylko w podskopie i użyteczny tylko po definicji). Możesz również użyć pełnego typu enum stuff
tylko raz w zakresie, ponieważ działa on jako definicja typu.
Definicja typu wyliczeniowego dla enum stuff
jest również obecna w obszarze pliku (użyteczna przed i poniżej), jak również deklaracja typu forward (Typ enum stuff
może mieć wiele deklaracji, ale tylko jedną definicja / dopełnienie w zakresie i może być przedefiniowane w podskopie). Działa również jako dyrektywa kompilatora, aby zastąpić a
rvalue 0
, b
z -4
, c
z 5
, d
Z -2
, e
z -3
, f
z -1
i g
z -2
w obecnym zakresie. Stałe wyliczenia są teraz stosowane po definicji aż 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 tagów współdzielona przez enum, struct i union jest oddzielny I musi być poprzedzony słowem kluczowym type (enum, struct lub union) W C tzn. po enum a {a} b
, enum a c
należy stosować, a nie a c
. Ponieważ przestrzeń nazw znaczników jest oddzielona od przestrzeni nazw identyfikatorów, {[32] } jest dozwolona, ale enum a {a, b} b
nie jest, ponieważ stałe są w tej samej przestrzeni nazw, co identyfikatory zmiennych, czyli przestrzeń nazw identyfikatorów. {[37] } jest również niedozwolone, ponieważ typedef-names są częścią przestrzeni nazw identyfikatorów.
Typ enum bool
i stałe następują następujący wzór 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 |
+-----------+-----+---------------+------+
To kompiluje 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++ enums może mieć typ
enum Bool: bool {True, False} Bool;
enum Bool: bool {True, False, maybe} Bool; //error
W tej sytuacji 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 bool. Również True, False i Bool nie mogą być pisane małymi literami, w przeciwnym razie będą zderzać się ze słowami kluczowymi języka. Enum również nie może mieć typu wskaźnika.
Zasady dla enum 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 Enums w C++ nie są już tylko niepodpisanymi liczbami całkowitymi itp., są również typu enum i mogą być przypisane tylko stałe w enum. 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 może być nadal używany dla enum nieoznaczonych.
#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że być zdefiniowane jako coś innego w zakresie, nie ma różnicy między ::w
a ::a::w
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55