fsa*_*asm 6 c c99 language-lawyer
我试图更好地理解 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;
};
Run Code Online (Sandbox Code Playgroud)
我可以使用 gcc-5.0 和 clang-3.5 在没有警告的情况下编译它,-std=c99 -Wall -Wextra -pedantic但是我在 gcc-4.8 中得到以下警告
warning: type of bit-field 'bitfield' is a GCC extension
Run Code Online (Sandbox Code Playgroud)
这里开始混乱。枚举作为位域是否被视为 int 或实现定义的类型?这是 GCC-4.8 中的错误还是他们改变了对标准的解释?将它与其他 C99 编译器一起使用是否安全?
枚举是位域实现定义的类型吗?
是的。
您所看到的是 gcc 的实现定义行为的变化。
当它在你引用的标准的部分说,一个位字段的类型必须为_Bool,int,unsigned int,或某些实现定义的类型。
甲enum类型与某些整数类型兼容。实验并查看 gcc 手册表明,对于 gcc,您enum e与unsigned int. 但该标准不允许位字段是一个类型的兼容与unsigned int。它实际上必须是类型unsigned int(兼容的类型不一定是相同的类型)。除了它也可以是其他一些实现定义的类型。
- 比其他可允许位字段类型
_Bool,signed int和unsigned int(C99 6.7.2.1)。在严格符合模式下不允许使用其他类型。
根据 gcc-5.2.0 的手册:
- 比其他可允许位字段类型
_Bool,signed int和unsigned int(C99和C11 6.7.2.1)。
long int即使在严格符合的模式下,也允许其他整数类型,例如, 和枚举类型。
所以你看到的是 gcc 行为的变化,即使在“严格符合模式”下也允许位域的更多类型。这不是 gcc 对标准解释的改变;这两种行为都是允许的。
使用enums 作为位域是不可移植的。符合标准的 C 编译器可能支持也可能不支持它们。(如果 gcc 保留了为此获得警告的能力,我个人会更喜欢它。)