如何在C中定义枚举类型(枚举)?

lin*_*lof 263 c enums

我不确定使用C枚举的正确语法是什么.我有以下代码:

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

但这不会编译,出现以下错误:

error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Joh*_*itb 449

值得指出的是,你并不需要一个typedef.您可以像下面这样做

enum strategy { RANDOM, IMMEDIATE, SEARCH };
enum strategy my_strategy = IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

这是一个风格问题,你喜欢typedef.没有它,如果要引用枚举类型,则需要使用enum strategy.有了它,你可以说strategy.

两种方式都有其优点和缺点.一个更罗嗦,但将类型标识符保存在tag-namespace中,它们不会与普通标识符冲突(想想struct stat和stat函数:这些也不会发生冲突),并且你会立即看到它是一个类型.另一个更短,但将类型标识符带入普通命名空间.

  • @Clearer:这段代码完美无缺.这是一个工作示例:https://ideone.com/T0YV17请注意,它在两行上都使用`enum`关键字. (19认同)
  • 它不应该是公认的答案,因为它是错误的.你不能使用枚举策略{...}; 在C中 - 你可以而且应该用C++来做. (6认同)
  • @AndyNugent 不要那样做!*_t 类型由 POSIX 保留 (2认同)

Ric*_*dle 368

声明一个枚举变量是这样的:

enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy my_strategy = IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

但是,您可以使用a typedef来缩短变量声明,如下所示:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy my_strategy = IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

有一个命名约定来区分类型和变量是一个好主意:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

  • 但OP想要一个匿名枚举类型的变量 (2认同)

Tar*_*arc 57

你试图宣布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;
}
Run Code Online (Sandbox Code Playgroud)

如果不是上述内容,则将第二行更改为:

...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...
Run Code Online (Sandbox Code Playgroud)

从警告中,你可以很容易地看到你的错误:

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
Run Code Online (Sandbox Code Playgroud)

因此编译器采用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;
}
Run Code Online (Sandbox Code Playgroud)


小智 48

当你说

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
Run Code Online (Sandbox Code Playgroud)

你创建了一个单一的实例变量,称为无名枚举的"策略".这不是一件非常有用的事情 - 你需要一个typedef:

typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType; 
StrategyType strategy = IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

  • 为什么这没用?如果我不关心这个类型的名字,我为什么要给它一个?这里唯一的目的是命名变量,因此可以为其分配新值. (9认同)
  • 我说这不是很有用,我不相信.当然,我不会在我自己的代码中使用这种模式.因人而异. (3认同)
  • @HorseSMith一个未命名的枚举不是很有用,因为你不能拥有该类型的任何其他变量,或函数参数或返回值.如果你只需要**一个变量**,那就没关系了. (3认同)
  • 有人不使用匿名枚举并不能证明它们没有用处.你不需要typedef.一些代码指南(kernel.org/doc/Documentation/CodingStyle)甚至不鼓励它. (3认同)
  • 这个答案也具有误导性.Tarc的答案是唯一合适的答案. (2认同)

Joh*_*ode 13

如上所述,您的代码没有任何问题.你确定你没有做过类似的事吗

int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
Run Code Online (Sandbox Code Playgroud)

错误消息指向哪些行?当它说"先前的'战略'宣言就在这里"时,"这里"是什么以及它显示了什么?

  • 他可能在文件范围内做了`strategy = IMMEDIATE;`.在所有函数之外的文件范围内不能进行赋值.所以编译器试图从错误中做到最好,并假设他的意思是"int strategy = IMMEDIATE;",此时发生了冲突. (6认同)
  • 这是最好的答案,在其他答案中有如此混乱,这是痛苦的. (2认同)

rog*_*ggc 11

@ThoAppelsin在发表评论的评论中是对的.问题中的代码段是有效且没有错误的.您遇到的错误必须是因为您的c源文件的任何其他位置的其他错误语法.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;
}
Run Code Online (Sandbox Code Playgroud)

这将输出1.

这也是有效的:

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

并将输出与以前相同.

如果你这样做:

enum {a,b,c};
enum {a,b,c};
Run Code Online (Sandbox Code Playgroud)

你会有错误,但如果你这样做:

enum alfa{a,b,c};
enum alfa;
Run Code Online (Sandbox Code Playgroud)

你不会有任何错误.

你可以这样做:

enum {a,b,c};
int aa=a;
Run Code Online (Sandbox Code Playgroud)

并且aa将与值的整数变量0.但你也可以这样做:

enum {a,b,c} aa= a;
Run Code Online (Sandbox Code Playgroud)

并且将具有相同的效果(即,aa作为一个int与0值).

你也可以这样做:

enum {a,b,c} aa= a;
aa= 7;
Run Code Online (Sandbox Code Playgroud)

并且aa将int与价值7.

因为你不能重复使用符号常量定义enum,正如我之前所说,如果你想使用以下方法声明int变量,你必须使用标签enum:

enum tag1 {a,b,c};
enum tag1 var1= a;
enum tag1 var2= b;
Run Code Online (Sandbox Code Playgroud)

使用typedef它是为了保证您每次enum tag1都要编写定义变量.有了typedef你可以键入Tag1:

typedef enum {a,b,c} Tag1;
Tag1 var1= a;
Tag1 var2= b;
Run Code Online (Sandbox Code Playgroud)

你也可以:

typedef enum tag1{a,b,c}Tag1;
Tag1 var1= a;
enum tag1 var2= b;
Run Code Online (Sandbox Code Playgroud)

最后要说的是,既然我们在谈论定义的符号常量,最好在使用时使用大写字母enum,例如:

enum {A,B,C};
Run Code Online (Sandbox Code Playgroud)

代替

enum {a,b,c};
Run Code Online (Sandbox Code Playgroud)


Rod*_*ddy 10

值得一提的是,在C++中,您可以使用"enum"来定义新类型,而无需使用typedef语句.

enum Strategy {RANDOM, IMMEDIATE, SEARCH};
...
Strategy myStrategy = IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

我发现这种方法更加友好.

[编辑 - 澄清了C++状态 - 我最初有这个,然后将其删除!]

  • 这个问题适用于C,而不适用于C++.在C中,上面的代码无效 - 你要么必须使用`typedef`,要么在变量声明中指定`enum`:enum Strategy {RANDOM,IMMEDIATE,SEARCH}; ... enum策略myStrategy = IMMEDIATE; (17认同)

Con*_*use 8

宣言似乎有些混乱.

当strategy之前谈到{RANDOM, IMMEDIATE, SEARCH}的在下面,

enum strategy {RANDOM, IMMEDIATE, SEARCH};
Run Code Online (Sandbox Code Playgroud)

您正在创建一个名为的新类型enum strategy.但是,在声明变量时,您需要使用enum strategy自身.你不能只是使用strategy.所以以下内容无效.

enum strategy {RANDOM, IMMEDIATE, SEARCH};
strategy a;
Run Code Online (Sandbox Code Playgroud)

同时,以下内容有效

enum strategy {RANDOM, IMMEDIATE, SEARCH};

enum strategy queen = RANDOM;
enum strategy king = SEARCH;
enum strategy pawn[100];
Run Code Online (Sandbox Code Playgroud)

当strategy后谈到{RANDOM, IMMEDIATE, SEARCH},要创建一个匿名枚举,然后宣称strategy是该类型的变量.

所以现在,你可以做类似的事情

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = RANDOM;
Run Code Online (Sandbox Code Playgroud)

但是,您不能声明任何其他类型的变量,enum {RANDOM, IMMEDIATE, SEARCH}因为您从未对其进行过命名.所以以下内容无效

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategy a = RANDOM;
Run Code Online (Sandbox Code Playgroud)

您也可以将这两个定义结合起来

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

a = RANDOM;
b = SEARCH;
enum strategy c = IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

Typedef 如前所述,用于创建较短的变量声明.

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
Run Code Online (Sandbox Code Playgroud)

现在你告诉编译器enum {RANDOM, IMMEDIATE, SEARCH}是同义的strategy.所以现在你可以自由地使用strategy变量类型了.您不再需要输入enum strategy.以下内容现在有效

strategy x = RANDOM;
Run Code Online (Sandbox Code Playgroud)

您还可以将Typedef与枚举名称结合使用

typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;
Run Code Online (Sandbox Code Playgroud)

使用此方法没有太大的优势,除了您现在可以使用strategy和enum strategyName互换.

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

enum strategyName a = RANDOM;
strategy b = SEARCH;
Run Code Online (Sandbox Code Playgroud)

  • 太好了,谢谢。可惜它离答案列表太远了,至少不是因为它_explicitly_用适当的解释解决了原始问题。 (2认同)