我不确定使用C枚举的正确语法是什么。我有以下代码:
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
但是这不能编译,出现以下错误:
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
我做错了什么?
答案 0 :(得分:444)
值得指出的是,你 typedef
。你可以像下面这样做
enum strategy { RANDOM, IMMEDIATE, SEARCH };
enum strategy my_strategy = IMMEDIATE;
这是一个风格问题,您是否更喜欢typedef
。没有它,如果要引用枚举类型,则需要使用enum strategy
。有了它,你可以说strategy
。
两种方式都有其优点和缺点。一个更罗嗦,但将类型标识符保留在tag-namespace中,它们不会与普通标识符冲突(考虑struct stat
和stat
函数:这些也不会发生冲突),你立刻就会发现它是一种类型。另一个更短,但将类型标识符带入普通命名空间。
答案 1 :(得分:362)
声明枚举变量的方式如下:
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;
答案 2 :(得分:55)
您尝试两次声明strategy
,这就是您收到上述错误的原因。以下工作没有任何投诉(使用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;
}
如果不是上述内容,则第二行更改为:
...
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
来声明一个名为strategy
的变量,其默认类型为int
,但之前已经声明了一个具有此名称的变量。
但是,如果您将作业放在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;
}
答案 3 :(得分:47)
当你说
时enum {RANDOM, IMMEDIATE, SEARCH} strategy;
您创建了一个名为“无策略枚举”的“策略”的实例变量。这不是一件非常有用的事情 - 你需要一个typedef:
typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType;
StrategyType strategy = IMMEDIATE;
答案 4 :(得分:13)
如上所述,您的代码没有任何问题。你确定你没有做过像
这样的事吗int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
错误消息指向哪些行?当它说“先前的'战略'宣言在这里”时,“这里”是什么以及它显示了什么?
答案 5 :(得分:11)
enum{a,b,c};
定义了三个符号常量(a
,b
和c
),它们是值为0
,1
和2
的整数但是当我们使用enum
时,因为我们通常不关心特定的整数值,所以我们更关心符号常量名的含义。
这意味着您可以拥有:
#include <stdio.h>
enum {a,b,c};
int main(){
printf("%d\n",b);
return 0;
}
,这将输出1
。
这也是有效的:
#include <stdio.h>
enum {a,b,c};
int bb=b;
int main(){
printf("%d\n",bb);
return 0;
}
并输出与之前相同的内容。
如果你这样做:
enum {a,b,c};
enum {a,b,c};
您将遇到错误,但如果您这样做:
enum alfa{a,b,c};
enum alfa;
你不会有任何错误。
你可以这样做:
enum {a,b,c};
int aa=a;
和aa
将是一个值为0
的整数变量。但你也可以这样做:
enum {a,b,c} aa= a;
并具有相同的效果(即aa
为int
且值为0
。
你也可以这样做:
enum {a,b,c} aa= a;
aa= 7;
和aa
将为int
,其值为7
。
因为您不能使用enum
重复符号常量定义,正如我之前所说,如果您想使用int
声明enum
变量,则必须使用标记:
enum tag1 {a,b,c};
enum tag1 var1= a;
enum tag1 var2= b;
typedef
的使用是为了保证您每次enum tag1
定义变量时都不会写。使用typedef
,您只需输入Tag1
:
typedef enum {a,b,c} Tag1;
Tag1 var1= a;
Tag1 var2= b;
你也可以:
typedef enum tag1{a,b,c}Tag1;
Tag1 var1= a;
enum tag1 var2= b;
最后要说的是,由于我们讨论的是定义的符号常量,因此在使用enum
时最好使用大写字母,例如:
enum {A,B,C};
而不是
enum {a,b,c};
答案 6 :(得分:10)
值得一提的是,在C ++ 中,您可以使用“enum”来定义新类型而无需typedef语句。
enum Strategy {RANDOM, IMMEDIATE, SEARCH};
...
Strategy myStrategy = IMMEDIATE;
我发现这种方法更加友好。
[编辑 - 澄清了C ++状态 - 我最初有这个,然后将其删除!]
答案 7 :(得分:7)
关于宣言似乎存在混淆。
当strategy
出现在{RANDOM, IMMEDIATE, SEARCH}
之前时,如下所示,
enum strategy {RANDOM, IMMEDIATE, SEARCH};
您正在创建名为enum strategy
的新类型。但是,在声明变量时,您需要使用enum strategy
本身。你不能只使用strategy
。所以以下内容无效。
enum strategy {RANDOM, IMMEDIATE, SEARCH};
strategy a;
同时,以下内容有效
enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy queen = RANDOM;
enum strategy king = SEARCH;
enum strategy pawn[100];
当strategy
出现在{RANDOM, IMMEDIATE, SEARCH}
之后,您正在创建一个匿名枚举,然后声明strategy
是该类型的变量。
现在,您可以执行类似
的操作enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = RANDOM;
但是,您不能声明类型为enum {RANDOM, IMMEDIATE, SEARCH}
的任何其他变量,因为您从未对其进行过命名。所以以下内容无效
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategy a = RANDOM;
您也可以将这两个定义结合起来
enum strategy {RANDOM, IMMEDIATE, SEARCH} a, b;
a = RANDOM;
b = SEARCH;
enum strategy c = IMMEDIATE;
如前所述, Typedef
用于创建更短的变量声明。
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
现在您告诉编译器enum {RANDOM, IMMEDIATE, SEARCH}
与strategy
同义。所以现在你可以自由地使用strategy
作为变量类型。您不再需要输入enum strategy
。以下内容现在有效
strategy x = RANDOM;
您还可以将Typedef与枚举名称结合使用以获取
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
使用此方法没有多大好处,除了您现在可以互换使用strategy
和enum strategyName
这一事实。
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategyName a = RANDOM;
strategy b = SEARCH;
答案 8 :(得分:2)
如果声明枚举名称,则不会发生错误。
如果未声明,则必须使用typedef
:
enum enum_name {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
它不会显示错误...
答案 9 :(得分:2)
我最喜欢和唯一使用的建筑总是:
typedef enum MyBestEnum
{
/* good enough */
GOOD = 0,
/* even better */
BETTER,
/* divine */
BEST
};
我相信这会消除你的问题。从我的观点来看,使用新类型是正确的选择。
答案 10 :(得分:1)
Tarc的答案是最好的。
enum讨论的大部分都是红鲱鱼。
比较此代码段: -
int strategy;
strategy = 1;
void some_function(void)
{
}
给出了
error C2501: 'strategy' : missing storage-class or type specifiers
error C2086: 'strategy' : redefinition
这个没有问题的编译。
int strategy;
void some_function(void)
{
strategy = 1;
}
变量strategy
需要在声明或函数内部等设置。您不能在全局范围内编写任意软件 - 特别是赋值。
他使用enum {RANDOM,IMMEDIATE,SEARCH}而不是int这一事实只与它让那些无法超越它的人感到困惑的程度相关。 问题中的重新定义错误消息表明这是作者做错了。
所以现在你应该能够看到为什么下面第一个例子是错误的,其他三个都没问题。
示例1.错误!
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
void some_function(void)
{
}
示例2.右。
enum {RANDOM, IMMEDIATE, SEARCH} strategy = IMMEDIATE;
void some_function(void)
{
}
示例3.右。
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
void some_function(void)
{
strategy = IMMEDIATE;
}
示例4.右。
void some_function(void)
{
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
}
如果你有一个工作程序,你应该能够将这些片段粘贴到你的程序中,看看有些编译,有些则没有。
答案 11 :(得分:0)
我尝试使用gcc并根据我的需要提出我被迫使用最后一个替代方案,编译时出错。
typedef enum 状态 {a = 0,b = 1,c = 2} 状态;
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);
答案 12 :(得分:0)
enum stuff q;
enum stuff {a, b=-4, c, d=-2, e, f=-3, g} s;
该声明充当具有完整类型的带符号整数s
的暂定定义,以及声明充当作用域中具有不完整类型的带符号整数q
的暂定定义(解析为整数因为类型定义存在于范围中的任何地方,所以必须在范围内键入类型(与任何暂定定义一样,可以使用相同类型{{1的不完整或完整版本)来重新声明标识符q
和s
}}或int
多次,但只能在范围内定义一次,即int q = 3;并且只能在子范围内重新定义,并且只能在定义之后使用。另外,您只能在范围内使用一次完整的enum stuff
类型,因为它充当类型定义。
enum stuff
的编译器枚举类型定义也出现在文件范围(可在之前和之下使用)以及正向类型声明(类型enum stuff
可以具有多个声明,但只有一个定义) / completion在范围内,可以在子范围内重新定义)。它也充当编译器指令,用右值enum stuff
替换a
,用0
替换b
,用-4
,{{1}替换c
}与5
,d
与-2
,e
与-3
和f
与-1
在当前范围内。现在,枚举常量将在定义之后应用,直到在不同枚举中的下一个重新定义为止,而该枚举不能在同一作用域级别。
g
枚举,结构和联合共享的标签名称空间是分开的,并且必须在C中以类型关键字(枚举,结构或联合)作为前缀,即在-2
之后必须使用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
enum a {a} b
。因为标签名称空间与标识符名称空间是分开的,所以允许enum a c
,但是a c
不允许,因为常量与变量标识符标识符空间位于同一名称空间中。也不允许使用enum a {a} b
,因为typedef名称是标识符名称空间的一部分。
enum a {a, b} b
的类型和常量在C中遵循以下模式:
typedef enum a {a,b} b
这在C语言中可以正常编译:
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 |
+-----------+-----+---------------+------+
在这种情况下,常量和标识符都具有相同的类型bool,如果无法用该类型表示数字,则会发生错误。也许= 2,这不是一个笨蛋。另外,True,False和Bool不能小写,否则它们将与语言关键字冲突。枚举也不能具有指针类型。
枚举的规则在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 ++中的枚举变量不再只是无符号整数等,它们还是枚举类型,只能在枚举中分配常量。但是,可以将其丢弃。
enum Bool: bool {True, False} Bool;
enum Bool: bool {True, False, maybe} Bool; //error
枚举类
#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;
}
与#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 class
但是由于不能将w定义为范围中的其他内容,因此#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);
}
之间没有区别