我不确定使用C枚举的正确语法是什么。我有以下代码:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
但是这不能编译,会出现以下错误:
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
我做错了什么?
我不确定使用C枚举的正确语法是什么。我有以下代码:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
但是这不能编译,会出现以下错误:
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
我做错了什么?
当前回答
你尝试两次声明策略,这就是为什么你会得到上面的错误。以下工作没有任何抱怨(编译gcc -ansi - petic -Wall):
#include <stdio.h>
enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;
int main(int argc, char** argv){
printf("strategy: %d\n", strategy);
return 0;
}
如果将第二行改为:
...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...
从警告中,你可以很容易地发现你的错误:
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
因此,编译器使用strategy = IMMEDIATE来声明一个默认类型为int的名为strategy的变量,但之前已经声明了一个具有此名称的变量。
然而,如果你把赋值放在main()函数中,它将是一个有效的代码:
#include <stdio.h>
enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;
int main(int argc, char** argv){
strategy=SEARCH;
printf("strategy: %d\n", strategy);
return 0;
}
其他回答
你尝试两次声明策略,这就是为什么你会得到上面的错误。以下工作没有任何抱怨(编译gcc -ansi - petic -Wall):
#include <stdio.h>
enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;
int main(int argc, char** argv){
printf("strategy: %d\n", strategy);
return 0;
}
如果将第二行改为:
...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...
从警告中,你可以很容易地发现你的错误:
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
因此,编译器使用strategy = IMMEDIATE来声明一个默认类型为int的名为strategy的变量,但之前已经声明了一个具有此名称的变量。
然而,如果你把赋值放在main()函数中,它将是一个有效的代码:
#include <stdio.h>
enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;
int main(int argc, char** argv){
strategy=SEARCH;
printf("strategy: %d\n", strategy);
return 0;
}
C
enum stuff q;
enum stuff {a, b=-4, c, d=-2, e, f=-3, g} s;
Declaration which acts as a tentative definition of a signed integer s with complete type and declaration which acts as a tentative definition of signed integer q with incomplete type in the scope (which resolves to the complete type in the scope because the type definition is present anywhere in the scope) (like any tentative definition, the identifiers q and s can be redeclared with the incomplete or complete version of the same type int or enum stuff multiple times but only defined once in the scope i.e. int q = 3; and can only be redefined in a subscope, and only usable after the definition). Also you can only use the complete type of enum stuff once in the scope because it acts as a type definition.
A compiler enumeration type definition for enum stuff is also made present at file scope (usable before and below) as well as a forward type declaration (the type enum stuff can have multiple declarations but only one definition/completion in the scope and can be redefined in a subscope). It also acts as a compiler directive to substitute a with rvalue 0, b with -4, c with 5, d with -2, e with -3, f with -1 and g with -2 in the current scope. The enumeration constants now apply after the definition until the next redefinition in a different enum which cannot be on the same scope level.
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
The tag namespace shared by enum, struct and union is separate and must be prefixed by the type keyword (enum, struct or union) in C i.e. after enum a {a} b, enum a c must be used and not a c. Because the tag namespace is separate to the identifier namespace, enum a {a} b is allowed but enum a {a, b} b is not because the constants are in the same namespace as the variable identifiers, the identifier namespace. typedef enum a {a,b} b is also not allowed because typedef-names are part of the identifier namespace.
enum bool类型和常量在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 |
+-----------+-----+---------------+------+
这在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++
在c++中,枚举可以有类型
enum Bool: bool {True, False} Bool;
enum Bool: bool {True, False, maybe} Bool; //error
在这种情况下,常量和标识符都具有相同的类型bool,如果一个数字不能用该类型表示,就会发生错误。也许= 2,这不是bool类型。此外,True、False和Bool不能小写,否则它们将与语言关键字冲突。枚举也不能有指针类型。
在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;
}
c++中的enum变量不再只是无符号整数等,它们也是enum类型,只能在enum中赋值常量。然而,这是可以抛弃的。
#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
}
枚举类
Enum struct与Enum类相同
#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
}
范围解析操作符仍然可以用于非范围枚举。
#include <stdio.h>
enum a: bool {l, w} ;
int main() {
enum a: bool {w, l} f;
printf("%llu", ::a::w);
}
但是因为w不能被定义为作用域中的其他东西,所以::w和::a::w之间没有区别
声明一个枚举变量是这样的:
enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy my_strategy = IMMEDIATE;
但是,你可以使用typedef来缩短变量声明,如下所示:
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy my_strategy = IMMEDIATE;
有一个命名约定来区分类型和变量是一个好主意:
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
如果为枚举声明名称,则不会发生错误。
如果没有声明,你必须使用类型定义:
enum enum_name {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
它不会显示错误…
当你说
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
创建一个名为“strategy”的实例变量。这不是一件非常有用的事情——你需要一个类型定义:
typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType;
StrategyType strategy = IMMEDIATE;