C #定义或枚举?

C #定义或枚举?,c,C,可能重复: 在C语言中编程时,在状态机中使用#define语句或枚举是否更好?由于状态是相关元素,我认为最好使用枚举来定义它们。我更喜欢枚举。它们更紧凑,更“安全”。您还可以暗示枚举中的顺序,这在状态机中可能会有所帮助#如果可能的话,应该避免使用define,因为它们将覆盖源代码中的所有事件,这可能会导致一些难以调试的意外操作。\define指令可能会产生许多意外后果,并且不遵循常见的范围规则。有相关数据时使用枚举 更多信息:[C++材料,但仍有一定的相关性]如果编译器支持enum,则首选此选

可能重复:


在C语言中编程时,在状态机中使用#define语句或枚举是否更好?

由于状态是相关元素,我认为最好使用枚举来定义它们。

我更喜欢枚举。它们更紧凑,更“安全”。您还可以暗示枚举中的顺序,这在状态机中可能会有所帮助#如果可能的话,应该避免使用define,因为它们将覆盖源代码中的所有事件,这可能会导致一些难以调试的意外操作。

\define
指令可能会产生许多意外后果,并且不遵循常见的范围规则。有相关数据时使用枚举


更多信息:[C++材料,但仍有一定的相关性]

如果编译器支持
enum
,则首选此选项。否则,请务必使用
#define
。所有C++编译器和现代C编译器都应该支持<代码> EnUM < /C>,但是较旧的编译器(特别是针对嵌入式平台的编译器)可能不支持<代码> EnUM < /C> 如果必须使用
#define
请确保使用括号定义常量,以避免预处理器错误:

#define RED_STATE    (1)
#define YELLOW_STATE (2)
#define GREEN_STATE  (3)

没有明确的答案
enum
为您提供范围和自动赋值,但不提供对常量类型的任何控制(始终
signed int
#define
忽略作用域,但允许您使用更好的键入功能:允许您选择常量类型(通过使用后缀或在定义中包含显式转换)


所以,为自己选择对自己更重要的东西。对于状态机,
enum
可能是一个更好的选择,除非您有很好的理由来控制类型。

enum
在您有独占选项时非常好,但您不能使用它们来定义位域标志,如下图所示:

#define SQ_DEFAULT 0x0
#define SQ_WITH_RED 0x1
#define SQ_WITH_BLUE 0x2

void paint_square(int flags);
然后,您可以使用以下颜色绘制红蓝色正方形:

paint_square(SQ_WITH_RED | SQ_WITH_BLUE);

…这在技术上是不重要的。编译器很可能会为这两种情况创建相同的机器代码,但枚举有三个优点:

  • 使用正确的编译器+调试器组合,调试器将按枚举名称而不是编号打印枚举变量。所以“StateBlahBlup”读起来比“41”好多了,不是吗

  • 您不必显式地为每个状态指定一个编号,如果您允许,编译器会为您进行编号。假设你已经有20个状态,你想在中间添加一个新的状态,在定义的情况下,你必须自己做所有的重新编号。在枚举的情况下,您只需添加状态,编译器将为您重新编号此新状态下的所有状态

  • 如果switch语句没有处理所有可能的枚举值,例如,因为您忘记处理某些值,或者因为枚举已扩展,但您也忘记更新处理枚举值的switch语句,则可以告诉编译器发出警告(如果存在
    默认情况,则不会发出警告,因为所有未显式处理的值都以默认情况结束)


  • 你想用什么就用什么

    尽管如此,每个人都说,我也希望把我算在内,为Enum投票

    如果像在状态机中一样使用相关数据,则应始终首选枚举,还可以在枚举中定义顺序,这将有助于实现状态机

    进一步的枚举将保证您的程序的安全,因为所有枚举都是它的类型,所以它们也将避免任何可能的混淆

    #定义不应该用在状态机或相关数据的情况下。无论如何,这是我的建议,但没有硬性规定


    此外,我还想补充一点,如果将来使用或被其他人阅读,enums将为您的代码增加更多可读性和可理解性。当您有一个非常大的程序,并且程序中有很多定义,而不是用于状态机时,这一点非常重要。

    您可以这样做让编译器检查
    #define
    值的类型的技巧

    #define VALUE_NAME ((TYPE_NAME) 12)
    

    然而,
    #define
    的真正问题是它可以在应用程序代码中重新定义。(当然,编译器会警告您这一点。)

    回答为“首选
    #define
    的问题的数量史蒂芬:主要是因为很多海报都被锁定在C++模式中,而问题是C。C和C++在这方面的差别是相当大的。事实上,在大多数情况下,你应该更喜欢<代码>定义< <代码>,但是在这个特定的情况下(状态机)“代码> EnUM <代码>确实是一种更好的方法。据我所知,复制的东西可能是“状态机中的状态”,稍微改变一下,但没有理由考虑“状态机状态”。可以使用什么定义或枚举来……@安德烈:同意C++进一步减少了对<代码>的定义,< <代码> >,但是自从C90<代码> const 已经成为一个识别的关键字……它杀死了99%的用法。最好使用
    enum
    。使用预处理器符号会使调试变得更加困难。显然,宏需要
    #define
    。因此,除了在某些情况下可能比编译器更擅长使用concat符号外,您认为c中的
    #define
    常量(自C90以来)有什么好处?(我应该补充,也许证明你的观点,我在C++中工作)@史蒂芬:<代码>代码> const <代码>对于这个目的是没有用的。这实际上就是我所说的差异。在C <代码> const 中不产生常数,在C++中它是这样做的。在C <代码> const < /Cord>中创建了一个“const对象”。,它不是常量,不能用于需要常量的地方。这就是为什么在C中,您的选择仅限于
    #define