c 语言的 enum 是个残废设计吧? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
miaowei
V2EX    问与答

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

  •  
  •   miaowei 2018-03-29 18:40:53 +08:00 4177 次点击
    这是一个创建于 2820 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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     Solana     4496 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 01:06 PVG 09:06 LAX 17:06 JFK 20:06
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86