V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
0littleboy
V2EX  ›  C

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

  •  1
     
  •   0littleboy · 364 天前 · 3068 次点击
    这是一个创建于 364 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如:

    /* 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
    

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

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

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

    宏可以嵌套宏,
    但是宏不能嵌套枚举常量。
    klwha
        7
    klwha  
       364 天前
    @icyalala 这个是不是和 c++里到目前为止还是很少见 constexpr 和 consteval 有人用一样?
    artnowben
        8
    artnowben  
       364 天前
    通常 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
        9
    weyou  
       364 天前
    @blindie 枚举类型可以 typedef 成一个类型用于变量,特别是作为函数参数, 一看就知道参数值的范围。 这种情况下可读性要比宏好的多。
    LXGMAX
        10
    LXGMAX  
       363 天前
    常量具有同一特征且值不需要指定:
    enum
    JANUARY = 0,
    FEBRUARY,
    MARCH
    ...

    反之
    #define GPIOA 0x080001
    #define GPIOB 0x080002
    macha
        11
    macha  
       363 天前
    主要还是习惯,尤其是定义错误码的时候,用枚举很变扭
    nmap
        12
    nmap  
       363 天前
    历史传承
    tomychen
        13
    tomychen  
       363 天前
    感觉是历史遗留问题

    enum 是 C89 后才有的特性

    再就是,不是所有常量都是顺序的数值+1
    ssw2
        14
    ssw2  
       363 天前
    C 语言枚举有定义域的坑,用起来远不如宏定义清晰
    noroot
        15
    noroot  
       362 天前
    看情况,现在一般情况应该是如果可以用枚举替代的话更建议用枚举,因为可以利用类型检查来规避一些错误。为什么更喜欢用宏大概是历史惯性。
    noroot
        16
    noroot  
       362 天前
    用枚举好像存在一个这样的问题:一些项目会利用编译器的特性指定了枚举的底层大小,这时候超过这个大小的枚举值可能会 UB 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1167 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 18:30 · PVG 02:30 · LAX 11:30 · JFK 14:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.