用C语言编程时,最好在状态机中使用#define语句或枚举吗?
答案 0 :(得分:46)
技术上没关系。编译器甚至很可能为这两种情况创建相同的机器代码,但枚举有三个优点:
使用正确的编译器+调试器组合,调试器将按枚举名称而不是按其编号打印枚举变量。所以“StateBlahBlup”读起来比“41”好得多,不是吗?
您没有明确地为每个州提供一个数字,如果您允许,编译器会为您编号。假设您已经有20个状态,并且您想在中间添加一个新状态,如果是定义,则必须自己进行所有重新编号。在枚举的情况下,您只需添加状态,编译器将为您重新编号低于此新状态的所有状态。
您可以告诉编译器警告您switch语句是否不处理所有可能的枚举值,例如:因为你忘了处理某些值,或者因为enum被扩展了但是你忘了也更新处理枚举值的switch语句(如果有default
的情况就不会发出警告,因为所有未明确处理的值最终都会默认情况)。
答案 1 :(得分:12)
由于状态是相关元素,我认为最好有一个定义它们的枚举。
答案 2 :(得分:9)
没有确定的答案。 enum
为您提供范围和自动值赋值,但不提供对常量类型的任何控制(始终为signed int
)。 #define
忽略作用域,但允许您使用更好的键入工具:让您选择常量类型(通过使用后缀或通过在定义中包含显式强制转换)。
所以,选择对你来说更重要的东西。对于状态机,enum
可能是更好的选择,除非您有充分的理由来控制类型。
答案 3 :(得分:8)
我更喜欢enum。它们更紧凑,更“安全”。您还可以在枚举中暗示订单,这可能对状态机有帮助。如果可能,应该避免使用#defines,因为它们会覆盖源代码中的所有实例,这可能会导致一些难以调试的意外操作。
答案 4 :(得分:2)
#define
指令可能会产生许多意想不到的后果,并且不遵循常见的范围规则。有相关数据时使用枚举。
更多信息:http://www.embedded.com/columns/programmingpointers/9900402?_requestid=341945 [C ++材料,但仍然有点相关]
答案 5 :(得分:2)
如果您的编译器支持enum
,那么这将是首选。如果做不到这一点,请务必使用#define
。所有C ++编译器和现代C编译器都应支持enum
,但较旧的编译器(特别是针对嵌入式平台的编译器)可能不支持enum
。
如果必须使用#define
,请确保用括号定义常量,以避免预处理器错误:
#define RED_STATE (1)
#define YELLOW_STATE (2)
#define GREEN_STATE (3)
答案 6 :(得分:1)
您可以使用此技巧使编译器检查#define
值的类型。
#define VALUE_NAME ((TYPE_NAME) 12)
然而#define
的真正问题是它可以在应用程序代码中重新定义。 (当然编译器会警告你。)
答案 7 :(得分:0)
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);
...您无法使用enum
。
答案 8 :(得分:0)
你可以使用你想要的任何东西。
尽管每个人都在说我也想把我加起来作为Enums的投票。
如果您使用相关数据(如果是状态机),则应始终首选枚举,您也可以在枚举中定义有助于实现状态机的顺序。
进一步的枚举将保证您的程序安全,因为所有枚举只是类型,所以他们也会避免任何可能的混淆。
在状态机或相关数据的情况下不应使用#define。无论如何,这是我的建议,但没有硬性规定。
另外,我想补充一点,即如果将来使用或者如果被其他人阅读,枚举将为您的代码添加更多可读性和可理解性。当你拥有一个非常大的程序并且程序中有很多#defines而不是你用于你的状态机时,这是一个重要的点。