为什么 C 语言程序员更偏爱使用宏定义一组常量, 而不使用枚举?

2023-04-26 16:49:39 +08:00
 0littleboy

比如:

/* open-only flags */
#define O_RDONLY        0x0000          /* open for reading only */
#define O_WRONLY        0x0001          /* open for writing only */

#define	EXIT_FAILURE	1
#define	EXIT_SUCCESS	0

这些定义成枚举,可读性不是更强吗

3084 次点击
所在节点    C
16 条回复
pursuer
2023-04-26 17:12:04 +08:00
我个人来说,一个变量可以是多组常量的组合的时候,用宏比较方便,然后就习惯用宏了
CodeCore
2023-04-26 17:39:45 +08:00
claude 的回答:
使用宏定义一组常量而不使用枚举的主要原因有:
1. 兼容性:宏定义只是简单的文本替换,可以在任何标准 C/C++中使用,而枚举是 C 语言特有的类型,在 C++中作为一种 scoped enum 使用。所以如果要确保代码在各种编译器和语言版本中都能编译通过,宏定义会更具兼容性。
2. 前向声明:对于枚举类型,在使用前必须将其定义,而宏定义可以在使用前就声明。这在 header 文件中定义常量时比较重要,可以先声明使用宏定义的常量,然后在源文件中定义具体值。
3. 类型安全:枚举有着严格的类型检查,只能用于和枚举类型兼容的场合。而宏定义只是简单替换,没有严格的类型,可以用于任何场合。这在一些特殊情况下会更灵活,但也可能引入 bug 。
4. 值的定义:枚举中的值必须是整数,而宏定义的值可以是任何文本,这在定义一些特殊常量时可能会更有用。
5. 可读性:宏定义中的值只是简单的文本替换,而不像枚举那样清晰地定义一个新类型和值。所以从可读性而言,枚举的表现会更好。
所以综上,当需要高兼容性、前向声明以及特殊值定义,可以考虑使用宏定义。其他时间优先考虑使用枚举,以获取类型安全检查、更清晰的语义和更好的可读性。也可以两者结合使用,根据具体情况选择。
blindie
2023-04-26 18:05:26 +08:00
// Type of animals
#define TIGER 0
#define CAT 1
#define HUMAN 2

enum animal {
TIGER = 0,
CAT,
HUMAN
}
可读性其实是差不多的。至于为啥 C 语言程序员更偏爱用宏可能是大家都在用入乡随俗?比如我就从来没在 C 里面写过枚举,没看到这个贴子之前我甚至都没想过这回事。
xtreme1
2023-04-26 18:10:54 +08:00
K&R C 一路沿袭下来的习惯吧, 枚举是 C89 的特性
icyalala
2023-04-26 18:14:04 +08:00
主要是历史原因,最初的 K&R 版本的 C 还不支持 enum 。
后来 ANSI C 也没明确 enum 的长度,而是可以由编译器决定。
另外如果常量是 flag ,需要用 or 来连接的话,用 enum 也不合适。
junyee
2023-04-26 19:27:54 +08:00
我说一点:

宏可以嵌套宏,
但是宏不能嵌套枚举常量。
klwha
2023-04-26 20:13:33 +08:00
@icyalala 这个是不是和 c++里到目前为止还是很少见 constexpr 和 consteval 有人用一样?
artnowben
2023-04-26 21:02:32 +08:00
通常 enum 的值是从 0 开始递增的;而宏的值是可以任意的,例如按 bit 位置 1 。

例子:
#define HTTP_F_CONTENT_LENGTH_AUTO 0x1
#define HTTP_F_CONTENT_LENGTH 0x2
#define HTTP_F_TRANSFER_ENCODING 0x4
#define HTTP_F_CLOSE 0x8

https://github.com/baidu/dperf/blob/main/src/http_parse.h
weyou
2023-04-26 23:47:32 +08:00
@blindie 枚举类型可以 typedef 成一个类型用于变量,特别是作为函数参数, 一看就知道参数值的范围。 这种情况下可读性要比宏好的多。
LXGMAX
2023-04-27 09:25:31 +08:00
常量具有同一特征且值不需要指定:
enum
JANUARY = 0,
FEBRUARY,
MARCH
...

反之
#define GPIOA 0x080001
#define GPIOB 0x080002
macha
2023-04-27 10:16:42 +08:00
主要还是习惯,尤其是定义错误码的时候,用枚举很变扭
nmap
2023-04-27 11:27:23 +08:00
历史传承
tomychen
2023-04-27 14:07:46 +08:00
感觉是历史遗留问题

enum 是 C89 后才有的特性

再就是,不是所有常量都是顺序的数值+1
ssw2
2023-04-27 17:57:27 +08:00
C 语言枚举有定义域的坑,用起来远不如宏定义清晰
noroot
2023-04-28 10:20:19 +08:00
看情况,现在一般情况应该是如果可以用枚举替代的话更建议用枚举,因为可以利用类型检查来规避一些错误。为什么更喜欢用宏大概是历史惯性。
noroot
2023-04-28 10:22:49 +08:00
用枚举好像存在一个这样的问题:一些项目会利用编译器的特性指定了枚举的底层大小,这时候超过这个大小的枚举值可能会 UB 。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/935684

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX