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

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

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

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

我做错了什么?


当前回答

Tarc的答案是最好的。

全会的许多讨论都是在转移话题。

比较以下代码片段:-

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;   
}

变量策略需要在声明中或在函数中设置。您不能在全局范围内编写任意软件——特别是赋值软件。

他使用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;
}

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

其他回答

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之间没有区别

值得一提的是,在c++中,你可以使用“enum”来定义一个新类型,而不需要typedef语句。

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

我发现这种方法更友好。

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

你尝试两次声明策略,这就是为什么你会得到上面的错误。以下工作没有任何抱怨(编译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;
}

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

int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;

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

当你说

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

创建一个名为“strategy”的实例变量。这不是一件非常有用的事情——你需要一个类型定义:

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