我试图更好地理解C99标准,但现在我对使用枚举作为结构中的位域以及它们被视为int还是实现定义类型感到困惑。 在查看C99的最终草案时,我找到了6.7.2.1段。 4
位字段的类型应为_Bool , signed int , unsigned int或其他实现定义类型的限定或非限定版本。
和6.7.2.2段。 4
每个枚举类型应与char ,有符号整数类型或无符号整数类型兼容。 类型的选择是实现定义的,但应能够表示枚举的所有成员的值。 …
所以我尝试使用这个简单的源代码
enum e { E0, E1 }; struct s { enum e bitfield : 4; };
我可以用gcc-5.0和clang-3.5使用-std=c99 -Wall -Wextra -pedantic
编译这个没有警告但是我用gcc-4.8得到以下警告
warning: type of bit-field 'bitfield' is a GCC extension
这里开始混乱。 枚举是否将位域视为int或实现定义的类型? 这是GCC-4.8中的错误还是他们改变了对标准的解释? 与其他C99编译器一起使用是否安全?
枚举是否是位域实现定义的类型?
是。
您所看到的是gcc的实现定义行为的变化。
正如您引用的标准部分所述,位字段必须是_Bool
, int
, unsigned int
类型或某些实现定义类型。
enum
类型与某种整数类型兼容。 实验和gcc手册的显示表明,对于gcc,你的enum e
与unsigned int
兼容。 但是该标准不允许位字段与unsigned int
兼容 。 它实际上必须是unsigned int
类型(兼容类型不一定是同一类型)。 除了它也可以是其他一些实现定义的类型。
根据gcc 4.8.4的手册 :
严格符合模式不允许其他类型。
根据gcc-5.2.0的手册:
即使在严格一致的模式下,也允许使用其他整数类型,例如
long int
和枚举类型。
所以你看到的是gcc行为的改变,即使在“严格符合模式”下也允许更多类型的位域。 这不是gcc对标准的解释的变化; 两种行为都是允许的。
使用enum
作为位字段是不可移植的。 符合标准的C编译器可能支持也可能不支持它们。 (如果gcc能够为此发出警告,我本人会更喜欢它。)
它可能是安全的,但不要这样做。 你违反了隐含的合同设计。 有点。 你提到了这个构造,但没有提到你是如何使用它的。 可能有一种更清洁的方式。
如果你有:
typedef enum { E0, E1, E2 } myenum_t; myenum_t val;
现在,如果您有各种switch语句,例如:
switch (val) { case E0: ... break; case E1: ... break; case E2: ... break; }
它们将在编译时进行检查,以确保您的switch
涵盖所有情况。 如果然后在枚举定义中添加E3
,编译器会将switch
语句标记为缺少E3
。 这很有用。
如果你开始咬住你的枚举值,你可能需要将你的switch
改为:
switch (val) { case E0: ... break; case E1: ... break; case E2: ... break; default: ... break; }
现在,如果您将E3
添加到枚举中,编译器将不会为丢失的case
标记您的switch
,因为它假设default
将处理它。 也许不是你想要的。
添加default
值通常用于调试错误的枚举值。
但是,如果你有:
typedef struct { unsigned int mask:8; unsigned int enval:8; unsigned int ident:8; unsigned int other:8; } mybit_t; mybit_t bval;
使用以下内容:
switch ((myenum_t) bval.enval) { ... }
可能有点清洁,也许更接近你真正希望实现的目标。
“隐含合同”是[在这种情况下]枚举旨在成为一组整数。 请注意,您还可以:
typedef enum { M0 = 1 << E0, M1 = 1 << E1, M2 = 1 << E2 } mymask_t;
并且,完成以下操作是完全正常的: bval.mask |= M2;
。 将位域切片和切块保留到int
,您可以在其中控制大小[种类]。 当使用标准的东西工作正常时,尝试应用半非便携式扩展没有任何优势。
以上就是c/c++开发分享枚举是否是位域实现定义的类型?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/544965.html