【问题标题】:What's the best way to declare an enum variable in C?在 C 中声明枚举变量的最佳方法是什么?
【发布时间】:2016-05-19 12:54:21
【问题描述】:

这个问题源于一个老问题:

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

该问题下方的答案相互冲突。例如,one answer 说“你需要使用 typedef”,another 辩称“你不需要 typedef”,评论下写着“你不能在 C 中使用 enum strategy { ... };——你不过可以而且应该在 C++ 中做到这一点。”这真的让我很困惑。更重要的是,OP 的代码在我所有的计算机上都使用 clang 编译,甚至没有警告。

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

【问题讨论】:

  • Johannes Schaub's answer 不解释这个吗?
  • @5gon12eder 是的,这就是“另一个”所指的。但是它下面的评论说我们不能用 C 写这个,正如我的问题中提到的那样。
  • 那条评论是错误的。
  • 引自维基百科:“C 编程语言的原始 K&R 方言没有枚举类型,但它们被添加到 C 的 ANSI 标准中,成为 C89。”
  • @Amnon 你的意思是C89 = ANSI C + enum type

标签: c variables enums


【解决方案1】:

C 有两个命名空间,一个用于变量和函数,另一个用于enums 和structs 之类的东西。让我们将第二个命名空间称为enum 命名空间。

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

这意味着无论何时要使用该枚举,都必须使用 enum 前缀。这是很多不方便的打字! (出于兴趣,同样适用于struct)。

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

typedef enum Foo {Bar1, Bar2} Foo;

第一个Foo 是它在enum 命名空间中的名称,第二个Foo 是它在函数和变量命名空间中的名称。

您无需在 C++ 中执行此操作:除非您明确使用 namespace,否则所有内容都在 global 命名空间中。

【讨论】:

    【解决方案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;

    然后您如何引用类型取决于您使用的形式。如果将类型声明为标记枚举,则可以通过引用标记在声明中使用它:

    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;
    

    至于哪种方式最好,答案还不是很清楚。如果您有一套既定的编码约定来解决这个问题,那么当然最好遵循这些约定。如果不是,那么您可以选择,但要保持一致,至少在任何给定项目中是这样。我倾向于认为typedefs 通常被过度使用,但使用 then 来命名enums 是我认为有意义的用途之一。但是,如果您这样做,那么我建议 nottypedef'd enums 声明标签 - 因为您追求一致性,因此明确提供 in 的机制em>一致性会适得其反。

    【讨论】:

      【解决方案3】:

      这有点主观,但在 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;
      

      【讨论】:

      • 使用_t 作为您自己的类型,并且来自本网站上最受尊敬的贡献者之一。对你来说顽皮的一步。
      • @Bathsheba 为什么?它也是事实上的行业标准命名约定,C 标准中没有任何内容不允许它,恰恰相反。参见 7.1.3 关于不允许的内容。标识符开头的下划线是您应该注意的。
      • @Bathsheba Aah 我知道你从哪里得到这个想法。来自 POSIX。我真的不在乎,我只关心 C 标准。如果 POSIX 选择偏离 C 标准或添加非标准限制,那是他们的问题,而不是我的问题。我个人从不使用 POSIX 系统。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多