在C中声明枚举变量的最佳方法是什么?

时间:2016-02-09 13:48:10

标签: c variables enums

这个问题来自一个老问题:

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

下面这个问题的答案只是相互冲突。例如,one answer表示"您需要使用typedef",another争论"您不需要typedef ",根据该评论撰写"您不能在C中使用enum strategy { ... }; - 您可以而且应该在C ++中使用它。"这真让我困惑。更重要的是,OP的代码在我的所有计算机上使用clang甚至没有警告编译。

所以,我的问题是:在C中,使用枚举变量的最佳做法是什么?

3 个答案:

答案 0 :(得分:2)

尽管有大量的选票和高度赞成的答案,但你提到的问题是基于一个完全错误的前提。它断言这段代码在C:

中是错误的
enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;

事实上,在C89,C99和C2011中,该代码完全没问题。它将变量strategy声明为具有给定枚举常量的匿名枚举类型,并将该变量初始化为为其类型定义的三个值之一。该问题的OP报告的错误消息可能是由不合格的编译器发出的,或者说该故事可能比OP提供的更多。

另一方面,这种形式的变量声明的实际用途相对较少,因为没有其他对象可以声明与在那里声明的变量具有相同的类型。声明枚举类型有两种方法可以在多个声明中使用:

  1. 使用标记声明类型:enum strategy_tag {RANDOM, IMMEDIATE, SEARCH} /* ... */ ;
  2. 使用typedef命名类型:typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
  3. 然后如何引用类型取决于您使用的形式。如果您将类型声明为带标记的枚举,那么您可以通过引用标记在声明中使用它:

    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有两个名称空间,一个用于变量和函数,另一个用于enumstruct s。让我们将第二个称为enum命名空间。

当您声明enum enum Foo {Bar1, Bar2};Foo时,枚举常量将被放入enum命名空间。

这意味着只要您想使用该枚举,就必须使用enum前缀。打字很不方便! (出于兴趣,这同样适用于struct)。

幸运的是,C允许您从enum命名空间中借用内容,因此它们也会出现在变量和函数命名空间中。您可以使用typedef

执行此操作

typedef enum Foo {Bar1, Bar2} Foo;

第一个Fooenum命名空间中的名称,第二个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;