【发布时间】:2012-07-02 05:55:44
【问题描述】:
在 C11 中工作,以下结构:
struct S {
unsigned a : 4;
_Bool b : 1;
};
GCC 将其布局为 unsigned(4 字节),其中使用了 4 位,然后是 _Bool(4 字节),其中使用了 1 位,总大小为 8 字节。
请注意,C99 和 C11 明确允许 _Bool 作为位字段成员。 C11 标准(可能还有 C99)也在 §6.7.2.1 'Structure and union specifiers' ¶11 中声明:
实现可以分配任何大到足以容纳位字段的可寻址存储单元。如果有足够的空间,结构中紧跟在另一个位域之后的位域应该被打包到同一单元的相邻位中。
所以我认为上面的成员b应该已经打包到分配给成员a的存储单元中,导致结构体的总大小为4字节。
当对两个成员使用相同的类型时,或者当一个是unsigned 而另一个是signed 时,GCC 行为正确并且打包确实发生了,但是类型unsigned 和_Bool 似乎被认为太不同了由 GCC 正确处理。
谁能证实我对标准的解释,这确实是一个 GCC 错误?
我也对解决方法感兴趣(一些编译器开关、编译指示、__attribute__...)。
我正在使用带有-std=c11 的 gcc 4.7.0(尽管其他设置显示相同的行为。)
【问题讨论】:
-
请注意,GCC 扩展
__attribute__ ((packed))可以应用于此处的成员,但与此问题正交(它导致大小为 4 + 1 = 5 的结构,即具有相同的问题。 ) -
相关:stackoverflow.com/questions/308364/…(但指的是 C++,在位域的措辞上并不那么严格。)
-
根据对上面链接的问题的回答,这种行为在 gcc 4.2.4 中没有发生,因此可能是此后的回归。
-
经过进一步研究,看起来这种行为可能特定于 Windows 上的 GCC,因为它试图匹配 MSVC 的行为。仍然有兴趣解决此问题。
标签: gcc c99 bit-fields c11 compiler-bug