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

How to define an enumerated type (enum) in C?

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

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

但这不会编译,错误如下:

1
2
error: conflicting types for ‘strategy’
error: previous declaration of ‘strategy’ was here

我做错什么了?


值得指出的是,你不需要一个typedef。你可以这样做

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

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

两种方法都有各自的利弊。其中一个更为复杂,但是将类型标识符保存到标记命名空间中,这样它们就不会与普通标识符冲突(想想struct statstat函数:它们也不会冲突),并且您会立即看到它是一个类型。另一个较短,但将类型标识符引入普通命名空间。


声明枚举变量的过程如下:

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

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

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

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

1
2
typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;


您试图声明strategy两次,这就是您得到上述错误的原因。以下工作无任何投诉(与gcc -ansi -pendantic -Wall汇编):

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

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

int main(int argc, char** argv){
    printf("strategy: %d
"
, strategy);

    return 0;
}

如果第二行不是上述行,则改为:

1
2
3
4
...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...

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

1
2
3
4
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()函数中,它将是一个有效的代码:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

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

int main(int argc, char** argv){
    strategy=SEARCH;
    printf("strategy: %d
"
, strategy);

    return 0;
}


当你说

1
enum {RANDOM, IMMEDIATE, SEARCH} strategy;

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

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


如前所述,您的代码没有任何问题。你确定你没有做过

1
2
3
int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;

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


@在他发表的对问题的评论中,透皮斯汀是对的。问题中发布的代码段是有效的,没有错误。您所犯的错误一定是因为C源文件的任何其他位置的其他语法错误。enum{a,b,c};定义了三个符号常数(abc,它们分别是值为012的整数,但是当我们使用enum时,因为我们通常不关心具体的整数值,我们更关心符号常数名称的意义。这意味着你可以拥有:

1
2
3
4
5
6
7
#include <stdio.h>
enum {a,b,c};
int main(){
  printf("%d
"
,b);
  return 0;
}

这将输出1

这也将有效:

1
2
3
4
5
6
7
8
#include <stdio.h>
enum {a,b,c};
int bb=b;
int main(){
  printf("%d
"
,bb);
  return 0;
}

并将输出与以前相同的结果。

如果您这样做:

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

您将有一个错误,但如果您这样做:

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

你不会有任何错误。

您可以这样做:

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

aa是一个整型变量,值为0。但你也可以这样做:

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

具有相同的效果(即,aaint值,0值)。

您也可以这样做:

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

aaint,值为7

由于不能使用enum重复符号常量定义,正如我前面所说,如果要使用enum声明intvars,则必须使用标记:

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

使用typedef是为了避免每次enum tag1定义变量时都写东西。使用typedef,您只需键入Tag1

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

您还可以拥有:

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

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

1
enum {A,B,C};

而不是

1
enum {A,B,C};


值得一提的是,在C++中,你可以使用"EnUM"来定义一个新类型,而不需要一个TyWIFF语句。

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

我觉得这种方法更友好。

[编辑-澄清C++状态-我原来有这个,然后删除它!]


声明似乎有点混乱。

strategy出现在{RANDOM, IMMEDIATE, SEARCH}之前,如下所示:

1
enum strategy {RANDOM, IMMEDIATE, SEARCH};

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

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

同时,以下内容是有效的

1
2
3
4
5
enum strategy {RANDOM, IMMEDIATE, SEARCH};

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

strategy出现在{RANDOM, IMMEDIATE, SEARCH}之后时,您将创建一个匿名枚举,然后将strategy声明为该类型的变量。

所以现在,你可以做一些像

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

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

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

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

1
2
3
4
5
enum strategy {RANDOM, IMMEDIATE, SEARCH} a, b;

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

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

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

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

1
strategy x = RANDOM;

您还可以将typedef与枚举名称组合以获取

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

除了可以互换使用strategyenum strategyName之外,使用这种方法没有太大的优势。

1
2
3
4
typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;

enum strategyName a = RANDOM;
strategy b = SEARCH;


我最喜欢和唯一使用的建筑总是:

1
2
3
4
5
6
7
8
9
typedef enum MyBestEnum
{
    /* good enough */
    GOOD = 0,
    /* even better */
    BETTER,
    /* divine */
    BEST
};

我相信这会消除你的问题。从我的观点来看,使用新类型是正确的选择。


如果声明枚举的名称,则不会发生错误。

如果没有声明,您必须使用typedef

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

它不会显示错误…


TARC的回答是最好的。

枚举的大部分讨论都是一个误区。

比较此代码段:

1
2
3
4
5
int strategy;
strategy = 1;  
void some_function(void)
{
}

哪个给了

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

它编译起来没有问题。

1
2
3
4
5
int strategy;
void some_function(void)
{
    strategy = 1;  
}

变量strategy需要在声明或函数内部等处设置。您不能在全局范围内编写任意的软件(尤其是分配)。

他使用枚举随机、立即、搜索而不是int,这一事实只与它使无法超越它的人感到困惑的程度有关。问题中的重新定义错误消息表明,这是作者所做的错误。

所以现在您应该能够理解为什么下面的第一个示例是错误的,而其他三个示例是正确的。

例1。错了!

1
2
3
4
5
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
void some_function(void)
{
}

例2。正确的。

1
2
3
4
enum {RANDOM, IMMEDIATE, SEARCH} strategy = IMMEDIATE;
void some_function(void)
{
}

例3。正确的。

1
2
3
4
5
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
void some_function(void)
{
    strategy = IMMEDIATE;
}

例4。正确的。

1
2
3
4
5
void some_function(void)
{
    enum {RANDOM, IMMEDIATE, SEARCH} strategy;
    strategy = IMMEDIATE;
}

如果你有一个正常工作的程序,你应该能够将这些代码片段粘贴到你的程序中,并且看到有些代码是编译的,而有些则不是。


我尝试使用gcc,并根据我的需要,不得不使用最后一个选项,以无错误编译。

typedef枚举状态a=0,b=1,c=2状态;

1
2
3
4
5
6
7
8
9
10
11
12
13
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
"
, now);
printf("Sate before = %d

"
, before);