这个问题来自一个老问题:
How to define an enumerated type (enum) in C?
下面这个问题的答案只是相互冲突。例如,one answer表示"您需要使用typedef
",another争论"您不需要typedef
",根据该评论撰写"您不能在C中使用enum strategy { ... };
- 您可以而且应该在C ++中使用它。"这真让我困惑。更重要的是,OP的代码在我的所有计算机上使用clang甚至没有警告编译。
所以,我的问题是:在C中,使用枚举变量的最佳做法是什么?
答案 0 :(得分:2)
尽管有大量的选票和高度赞成的答案,但你提到的问题是基于一个完全错误的前提。它断言这段代码在C:
中是错误的enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
事实上,在C89,C99和C2011中,该代码完全没问题。它将变量strategy
声明为具有给定枚举常量的匿名枚举类型,并将该变量初始化为为其类型定义的三个值之一。该问题的OP报告的错误消息可能是由不合格的编译器发出的,或者说该故事可能比OP提供的更多。
另一方面,这种形式的变量声明的实际用途相对较少,因为没有其他对象可以声明与在那里声明的变量具有相同的类型。声明枚举类型有两种方法可以在多个声明中使用:
enum strategy_tag {RANDOM, IMMEDIATE, SEARCH} /* ... */ ;
typedef
命名类型:typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
然后如何引用类型取决于您使用的形式。如果您将类型声明为带标记的枚举,那么您可以通过引用标记在声明中使用它:
enum strategy_tag my_strategy = RANDOM;
。如果您将类型声明为typedef
' d名称,则使用定义的名称作为类型名称
strategy_type my_strategy = IMMEDIATE;
。这些并不是唯一的;您可以标记enum
并为其声明typedef
,单独声明......
enum strategy_tag {RANDOM, IMMEDIATE, SEARCH};
typedef enum strategy_tag strategy_type;
......甚至在一个......
typedef enum strategy_tag {RANDOM, IMMEDIATE, SEARCH} strategy_type;
。如果您使用两种形式的类型声明,那么您可以在变量声明中使用其中一种或两种形式的类型说明符。
此外,请注意枚举标记,类型名称和变量名称的名称空间都是独立的,因此尽管可能有点令人困惑,但您可以这样做:
typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy strategy = RANDOM;
enum strategy strategy2 = strategy;
至于哪种方式最好,答案不是那么清楚。如果您有一套既定的编码约定来解决这个问题,那么当然最好遵循这些约定。如果没有那么你可以选择,但至少在任何给定的项目中保持一致。我倾向于认为typedef
在一般情况下被过度使用,但是使用它来命名enum
是我认为有意义的用途之一。但是,如果您这样做,那么我建议不为typedef
' d enum
声明标签 - 因为您在一致性后明确提供 in 一致性的机制适得其反。
答案 1 :(得分:1)
C有两个名称空间,一个用于变量和函数,另一个用于enum
和struct
s。让我们将第二个称为enum
命名空间。
当您声明enum
enum Foo {Bar1, Bar2};
,Foo
时,枚举常量将被放入enum
命名空间。
这意味着只要您想使用该枚举,就必须使用enum
前缀。打字很不方便! (出于兴趣,这同样适用于struct
)。
幸运的是,C允许您从enum
命名空间中借用内容,因此它们也会出现在变量和函数命名空间中。您可以使用typedef
:
typedef enum Foo {Bar1, Bar2} Foo;
第一个Foo
是enum
命名空间中的名称,第二个Foo
是函数和变量命名空间中的名称。
您不需要在C ++中执行此操作:除非您明确使用namespace
,否则所有内容都在全局命名空间中。
答案 2 :(得分:1)
这有点主观,但C和C ++都有行业事实上的标准。它是:
如果需要声明类型的实例(变量),则应该将类型定义与变量声明完全分开。
当你混淆它们时,代码会让你感到困惑。这适用于枚举和所有其他类型。例如:
typedef enum
{
THIS,
THAT
} mytype_t;
...
mytype_t variable;
但是,作为一种特殊情况:如果您不打算声明某种类型的任何变量,只是想要一种比#define
更可读的方式来枚举属于同一组的几个整数常量那么这样做很好:
enum
{
THIS_CONSTANT = 123,
THAT_CONSTANT = 567
};
...
int something = THIS_CONSTANT + THAT_CONSTANT;