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

发布于 2024-07-26 10:10:26 字数 320 浏览 3 评论 0原文

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

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

但这无法编译,并出现以下错误:

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

我做错了什么?

I'm not sure what the proper syntax for using C enums is. I have the following code:

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

But this does not compile, with the following error:

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

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

酒绊 2024-08-02 10:10:27

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

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

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

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

It's worth mentioning that in C++ you can use "enum" to define a new type without needing a typedef statement.

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

I find this approach a lot more friendly.

[edit - clarified C++ status - I had this in originally, then removed it!]

二货你真萌 2024-08-02 10:10:27

@ThoAppelsin 对所发布问题的评论是正确的。 问题中发布的代码片段是有效的并且没有错误。 您遇到的错误一定是因为 c 源文件的任何其他位置存在其他错误语法。 enum{a,b,c}; 定义了三个符号常量(abc),它们是分别具有值 012 的整数,但是当我们使用 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 是一个具有 0 值的 int)。

您也可以这样做:

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

@ThoAppelsin in his comment to question posted is right. The code snippet posted in the question it is valid and with no errors. The error you have must be because other bad syntax in any other place of your c source file. enum{a,b,c}; defines three symbolic constants (a, b and c) which are integers with values 0,1 and 2 respectively, but when we use enum it is because we don't usually care about the specific integer value, we care more about the meaning of the symbolic constant name.
This means you can have this:

#include <stdio.h>
enum {a,b,c};
int main(){
  printf("%d\n",b);
  return 0;
}

and this will output 1.

This also will be valid:

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

and will output the same as before.

If you do this:

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

you will have an error, but if you do this:

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

you will not have any error.

you can do this:

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

and aa will be an integer variable with value 0. but you can also do this:

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

and will have the same effect (that is, aa being an int with 0 value).

you can also do this:

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

and aa will be int with value 7.

because you cannot repeat symbolic constant definition with the use of enum, as i have said previously, you must use tags if you want to declare int vars with the use of enum:

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

the use of typedef it is to safe you from writing each time enum tag1 to define variable. With typedef you can just type Tag1:

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

You can also have:

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

Last thing to say it is that since we are talking about defined symbolic constants it is better to use capitalized letters when using enum, that is for example:

enum {A,B,C};

instead of

enum {a,b,c};
夜无邪 2024-08-02 10:10:27

该声明似乎存在混乱。

strategy 位于 {RANDOM, IMMEDIATE, SEARCH} 之前(如下所示)时,

enum strategy {RANDOM, IMMEDIATE, SEARCH};

您将创建一个名为 enum 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作为变量类型。 您不再需要输入枚举策略。 以下内容现在有效

strategy x = RANDOM;

您还可以将 Typedef 与枚举名称结合起来获取

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

除了您现在可以使用 strategyenumstrategyName 可以互换。

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

enum strategyName a = RANDOM;
strategy b = SEARCH;

There seems to be a confusion about the declaration.

When strategycomes before {RANDOM, IMMEDIATE, SEARCH} as in the following,

enum strategy {RANDOM, IMMEDIATE, SEARCH};

you are creating a new type named enum strategy. However, when declaring the variable, you need to use enum strategy itself. You cannot just use strategy. So the following is invalid.

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

While, the following is valid

enum strategy {RANDOM, IMMEDIATE, SEARCH};

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

When strategy comes after {RANDOM, IMMEDIATE, SEARCH}, you are creating an anonymous enum and then declaring strategy to be a variable of that type.

So now, you can do something like

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

However, you cannot declare any other variable of type enum {RANDOM, IMMEDIATE, SEARCH} because you have never named it. So the following is invalid

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

You can combine both the definitions too

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

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

Typedef as noted before is used for creating a shorter variable declaration.

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;

Now you have told compiler that enum {RANDOM, IMMEDIATE, SEARCH} is synonomous to strategy. So now you can freely use strategy as variable type. You don't need to type enum strategy anymore. The following is valid now

strategy x = RANDOM;

You can also combine Typedef along with enum name to get

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

There's not much advantage of using this method apart from the fact that you can now use strategy and enum strategyName interchangeably.

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

enum strategyName a = RANDOM;
strategy b = SEARCH;
心如荒岛 2024-08-02 10:10:27

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

如果未声明,则必须使用 typedef

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

它不会显示错误...

If you declare the name for enumeration no error will occur.

If not declared, you have to use a typedef:

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

It will not display an error...

花开浅夏 2024-08-02 10:10:27

我最喜欢且唯一使用的结构始终是:

typedef enum MyBestEnum
{
    /* Good enough */
    GOOD = 0,
    /* Even better */
    BETTER,
    /* Divine */
    BEST
};

我相信这会解决您遇到的问题。 从我的角度来看,使用新类型是正确的选择。

My favorite and only-used construction always was:

typedef enum MyBestEnum
{
    /* Good enough */
    GOOD = 0,
    /* Even better */
    BETTER,
    /* Divine */
    BEST
};

I believe that this will remove your problem you have. Using a new type is, from my point of view, the right option.

完美的未来在梦里 2024-08-02 10:10:27

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

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

如果您有一个可以运行的程序,您应该能够将这些片段粘贴到您的程序中,并看到有些可以编译,有些则不能。

Tarc's answer is the best.

Much of the enum discussion is a red herring.

Compare this code snippet:

int strategy;
strategy = 1;   

void some_function(void) 
{
}

which gives

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

with this one which compiles with no problem.

int strategy;

void some_function(void) 
{
    strategy = 1;   
}

The variable strategy needs to be set at declaration or inside a function, etc. You cannot write arbitrary software—assignments in particular—at the global scope.

The fact that he used enum {RANDOM, IMMEDIATE, SEARCH} instead of int is only relevant to the extent that it has confused people that can't see beyond it.
The redefinition error messages in the question show that this is what the author has done wrong.

So now you should be able to see why the first of the example below is wrong and the other three are okay.

Example 1. Wrong!

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

void some_function(void) 
{
}

Example 2. Right.

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

void some_function(void) 
{
}

Example 3. Right.

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

void some_function(void) 
{
    strategy = IMMEDIATE;
}

Example 4. Right.

void some_function(void) 
{
    enum {RANDOM, IMMEDIATE, SEARCH} strategy;
    strategy = IMMEDIATE;
}

If you have a working program you should just be able to paste these snippets into your program and see that some compile and some do not.

凉薄对峙 2024-08-02 10:10:27

我尝试使用 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);

I tried with GCC and come up with for my need, I was forced to use the last alternative, to compile without error.

typedef enum state {a = 0, b = 1, c = 2} state;

As in:

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);
寂寞陪衬 2024-08-02 10:10:27

C

enum stuff q;
enum stuff {a, b=-4, c, d=-2, e, f=-3, g} s;

声明充当具有完整类型的有符号整数 s 的暂定定义,以及充当范围内不完整类型的有符号整数 q 的暂定定义(其中解析为作用域中的完整类型,因为类型定义存在于作用域中的任何位置)(与任何暂定定义一样,标识符 qs 可以使用以下命令重新声明多次使用相同类型 intenum stuff 的不完整或完整版本,但仅在范围内定义一次,即 int q = 3;并且只能在子范围内重新定义,并且只能在定义之后使用)。 此外,您只能在作用域中使用完整类型的枚举内容一次,因为它充当类型定义。

enum stuff 的编译器枚举类型定义也出现在文件范围内(在之前和之后可用)以及前向类型声明(类型 enum stuff 可以有多个声明,但作用域中只有一个定义/完成,并且可以在子作用域中重新定义)。 它还充当编译器指令,用 r 替换 a -value 0b-4c5 >、d-2e-3f 与 < code>-1 和 g 以及 -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、struct和union共享的标签命名空间是独立的,必须以C语言中的type关键字(enum、struct或union)作为前缀,即在enum a {a} b之后,必须使用 enum a c 而不是 a c。 由于标记命名空间与标识符命名空间是分开的,因此允许使用 enum a {a} b,但不允许使用 enum a {a, b} b,因为常量位于与变量标识符相同的命名空间,标识符命名空间。 typedef enum a {a,b} b 也是不允许的,因为 typedef-names 是标识符命名空间的一部分。

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 |
+-----------+-----+---------------+------+

这表明常量类型基于分配给它的文字,并且没有后缀的整数文字通常总是遵循 int > > 长整数> long long int字符文字也是 C 中的 int,但不是 C++)。 然而,枚举类型似乎是可以表示枚举中定义的所有常量的最小类型(并且当所有整数均为正数时,无论出于何种原因,更倾向于选择 unsigned 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,这不是一个布尔值。 另外,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. A forward declaration of enum
          // type is 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 it is 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++ 中的枚举变量不再只是无符号整数等; 它们也是枚举类型,只能在枚举中分配常量。 然而,这可以被抛弃。

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

枚举类

枚举结构枚举类相同。

#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 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 r-value 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.

The type of enum bool and the constants follow the following pattern in 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 |
+-----------+-----+---------------+------+

Which shows that the constant type is based on the literal assigned to it, and integer literals without a suffix always customarily follow int > long int > long long int (and a character literal is also an int in C, but not C++). The enum type, however, appears to be the smallest type that can represent all constants defined in the enum (and prefers to choose unsigned int when all the integers are positive, for whatever reason).

This compiles fine in 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++

In C++, enums can have a type

enum Bool: bool {True, False} Bool;
enum Bool: bool {True, False, maybe} Bool; // Error

In this situation, the constants and the identifier all have the same type, bool, and an error will occur if a number cannot be represented by that type. Maybe = 2, which isn't a bool. Also, True, False and Bool cannot be lower case, otherwise they will clash with language keywords. An enum also cannot have a pointer type.

The rules for enums are different in C++.

#include <iostream>

c j; // Not allowed, unknown type name c before
     //  enum c{f} p; line
enum c j; // Not allowed. A forward declaration of enum
          // type is 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 it is 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;
}

Enums variables in C++ are no longer just unsigned integers, etc.; they're also of enum type and can only be assigned constants in the enum. This can however be cast away.

#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 classes

enum struct is identical to enum class

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

The scope resolution operator can still be used for non-scoped enums.

#include <stdio.h>

enum a: bool {l, w};

int main() {
  enum a: bool {w, l} f;
  printf("%llu", ::a::w);
}

But because w cannot be defined as something else in the scope, there isn't any difference between ::w and ::a::w.

遇见了你 2024-08-02 10:10:26

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

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

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

两种方式都有其优点和缺点。 一个更冗长,但将类型标识符保留在标记命名空间中,这样它们就不会与普通标识符冲突(想想 struct stat 和 stat 函数:这些不也不冲突),并且您立即看到它是一种类型。 另一个更短,但将类型标识符带入普通命名空间。

It's worth pointing out that you don't need a typedef. You can just do it like the following

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

It's a style question whether you prefer typedef. Without it, if you want to refer to the enumeration type, you need to use enum strategy. With it, you can just say strategy.

Both ways have their pro and cons. The one is more wordy, but keeps type identifiers into the tag-namespace where they won't conflict with ordinary identifiers (think of struct stat and the stat function: these don't conflict either), and where you immediately see that it's a type. The other is shorter, but brings type identifiers into the ordinary namespace.

山人契 2024-08-02 10:10:26

声明枚举变量的方式如下:

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;

Declaring an enum variable is done like this:

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

However, you can use a typedef to shorten the variable declarations, like so:

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

Having a naming convention to distinguish between types and variables is a good idea:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;
作死小能手 2024-08-02 10:10:26

您尝试声明strategy两次,这就是您收到上述错误的原因。 以下内容没有任何抱怨(使用 gcc 编译 -ansi -迂腐 -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;
}

You're trying to declare strategy twice, and that's why you're getting the above error. The following works without any complaints (compiled with gcc -ansi -pedantic -Wall):

#include <stdio.h>

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

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

    return 0;
}

If instead of the above, the second line were changed to:

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

From the warnings, you could easily see your mistake:

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

So the compiler took strategy = IMMEDIATE for a declaration of a variable called strategy with default type int, but there was already a previous declaration of a variable with this name.

However, if you placed the assignment in the main() function, it would be a valid code:

#include <stdio.h>

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

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

    return 0;
}
你在我安 2024-08-02 10:10:26

当您说

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

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

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

When you say

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

you create a single instance variable, called 'strategy' of a nameless enum. This is not a very useful thing to do - you need a typedef:

typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType; 
StrategyType strategy = IMMEDIATE;
墨落成白 2024-08-02 10:10:26

正如所写,您的代码没有任何问题。 您确定您没有做过类似

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

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

As written, there's nothing wrong with your code. Are you sure you haven't done something like

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

What lines do the error messages point to? When it says "previous declaration of 'strategy' was here", what's "here" and what does it show?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文