V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
miaowei
V2EX  ›  问与答

c 语言的 enum 是个残废设计吧?

  •  
  •   miaowei · 2018-03-29 18:40:53 +08:00 · 3676 次点击
    这是一个创建于 2420 天前的主题,其中的信息可能已经有所发展或是发生改变。
    enum 设计的初衷是好的,像
    enum colorbase{red = 0xff0000, green =0xff00, blue=0xff};
    它定义了一个整型,且这个整型比正常的 int 的取值范围小,因为三基色只有三个值. 用枚举很合适.
    但我们对 enum 类型的变量赋值时,C 编译器又不做类型检查(肯定是 C 标准没要求):
    enum colorbase x;
    x = red; //正确
    x = 0; //也正确 ?!
    那 enum 的意义何在?仅仅是增加一点代码可读性?用它当然是想让编译器帮着检查啊.

    c++对 enum 的实现就很让人满意,上面的 x=0, g++会报错:
    error: invalid conversion from ‘ int ’ to ‘ colorbase ’

    我对 C 的 enum 好奇很久了,对 C++又不熟,今天是偶然发现 C++的实现正合我意,赶紧发帖子唠叨两句...哎,其实我用过一阵子 C++, 其它都还好,就是受不了 void *赋值给指针时还要显式的做类型转换,不然大概早切换过去了.
    24 条回复    2018-03-31 20:42:21 +08:00
    Tompes
        1
    Tompes  
       2018-03-29 19:01:41 +08:00


    惊了,这算自己吃设定么......
    liuminghao233
        2
    liuminghao233  
       2018-03-29 19:17:33 +08:00 via iPhone
    enum 我是拿来放 switch 用的
    but0n
        3
    but0n  
       2018-03-29 23:14:09 +08:00
    <img src="https://user-images.githubusercontent.com/7625588/38096736-30e4b026-33a6-11e8-9bac-529e4ee58e8b.png">
    https://user-images.githubusercontent.com/7625588/38096736-30e4b026-33a6-11e8-9bac-529e4ee58e8b.png

    main.cpp:30:9: error: assigning to 'enum cb' from incompatible type 'int'
    b = 0;
    ^
    1 error generated.
    make[1]: *** [main.o] Error 1
    make: *** [main] Error 2



    enum cb {
    r = 0xFF0000,
    g = 0xFF00,
    b = 0xFF,
    };

    int main(int argc, char const *argv[]) {
    enum cb a, b;
    a = r;
    b = 0;
    printf("hello, %d\, %dn", a, b);

    return 0;
    }

    怎么说
    ysc3839
        4
    ysc3839  
       2018-03-29 23:20:08 +08:00
    @but0n 你这是 C++,楼主也说了 C++ 有类型检查。
    am241
        5
    am241  
       2018-03-29 23:31:42 +08:00
    c 本来就是弱类型语言,在明白怎么回事的情况下,允许用户使用各种黑科技。把"0"强制转换成函数指针然后 call 过去的用法也很常见

    enum 至少有个用途是可以自增:如果一个变量代表了 n 个状态,用户又不在乎用哪些值来代表这些状态的时候,用 enum 就很合适了
    but0n
        6
    but0n  
       2018-03-30 00:25:12 +08:00 via iPhone
    @ysc3839 忘改后缀名了……我是拿 gcc 编译的 印象中-Wall 会有警告的,明天试试
    sinxccc
        7
    sinxccc  
       2018-03-30 00:49:49 +08:00
    能增加代码可读性还不够么?

    代码写出来是让人读的。
    geelaw
        8
    geelaw  
       2018-03-30 01:01:41 +08:00 via iPhone
    就很迷…… void * 换类型需要显式转换难道不是和 int to enum 需要显式转换一样是好事儿么
    vincentxue
        9
    vincentxue  
       2018-03-30 03:33:03 +08:00
    楼主你没说错。

    C 中的枚举类型的作用是让程序员更清楚地编写程序,它实际上就是一组整数(其实也不一定,只是通常这样假设)常量,最主要的作用就是省去你要写很多 #define。

    C++ 中的 enum 是你创建的一个类型。

    clang 是支持 C enum 类型检查的。
    vincentxue
        10
    vincentxue  
       2018-03-30 03:35:42 +08:00
    @Tompes 你这输出没毛病啊。。
    liuhaotian
        11
    liuhaotian  
       2018-03-30 07:06:59 +08:00 via iPhone
    You can do a enum like

    enum status {
    ST_READY = 1 << 0, /* 1 */
    ST_WAIT = 1 << 1, /* 2 */
    ST_ERROR = 1 << 2, /* 4 */
    ST_HALT = 1 << 3, /* 8 */
    ST_ETC = 1 << 4, /* 16 */
    };
    Then define an object of that type

    enum status status;
    and set it to the bitwise OR of some 'simple' statuses

    status = ST_WAIT | ST_ERROR; /* recoverable error */
    Note that the value ST_WAIT | ST_ERROR is 6 and that that value is not part of the enum.

    SOF: https://stackoverflow.com/a/7431680
    pkookp8
        12
    pkookp8  
       2018-03-30 07:20:42 +08:00 via Android
    在我看来枚举和宏定义没差别。。。
    blahgeek
        13
    blahgeek  
       2018-03-30 08:25:21 +08:00 via iPhone

    rust 的 enum 了解一下
    Tompes
        14
    Tompes  
       2018-03-30 09:47:42 +08:00
    @vincentxue
    从语言设定来说 C 的 enum 是不能赋值为除定义的枚举值以外值的啊!
    而且就这 0 也不是任何枚举元素的序号...
    gggxxxx
        15
    gggxxxx  
       2018-03-30 10:01:49 +08:00
    enum 的意义是一种常用的抽象方法啊,大多数编程语言都有。赋值需求直接用变量来做不是更合理?
    另一方面 c 语言算很古老的了,不能拿现代新编程语言来对比。
    geelaw
        16
    geelaw  
       2018-03-30 10:11:17 +08:00
    @liuhaotian #11 an enum
    @Tompes #14 C 语言没有这样的设定,通常来说支持 enum 的语言都允许 enum 类型取所有 underlying type 允许的值
    xeaglex
        17
    xeaglex  
       2018-03-30 19:33:52 +08:00 via Android
    @am241 C 是弱类型语言?
    miaowei
        18
    miaowei  
    OP
       2018-03-30 22:26:19 +08:00
    @am241 自增的确是方便,我也经常用到,但不支持类型检查,感觉这个关键字就废了一大半。
    miaowei
        19
    miaowei  
    OP
       2018-03-30 22:28:00 +08:00
    @but0n 加_Wall 没用,我试过了。
    miaowei
        20
    miaowei  
    OP
       2018-03-30 22:32:48 +08:00
    @geelaw 一个指针,我声明为 void*显然是想避开类型检查,一个整型,我声明为 enum,显然是需要编译器给我掌个眼。就我一个人是这样想的?
    miaowei
        21
    miaowei  
    OP
       2018-03-30 22:35:39 +08:00
    @sinxccc 主要是
    @vincentxue clang 支持?多谢,我回去试一下。
    geelaw
        22
    geelaw  
       2018-03-31 01:53:58 +08:00 via iPhone
    @miaowei void * 表达的是“不从指针的类型而是从其他地方知道是什么类型”而不是“自动变成任何类型”。

    为什么你不想“写 enum 是为了定义几个字面量”呢?
    but0n
        23
    but0n  
       2018-03-31 16:47:03 +08:00
    @miaowei clang 应该可以的 你试试
    miaowei
        24
    miaowei  
    OP
       2018-03-31 20:42:21 +08:00
    @but0n 嗯,刚找到选项-Wenum-conversion -Wassign-enum . 在 google 上和 SO 上找一圈没找到,在 reddit 上找到的... gcc 不支持这两个选项.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1051 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 19:36 · PVG 03:36 · LAX 11:36 · JFK 14:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.