在C11中工作时,下面的结构体:
由GCC布置为一个无符号的(4字节),其中使用了4位,后跟一个_Bool (4字节),其中使用了1位,总大小为8字节。
请注意,C99和C11特别允许_Bool作为位字段成员。 C11标准(可能也是C99)还在§6.7.2.1“结构和联合说明符” ¶11下规定:
实现可以分配任何足够大以容纳位字段的可寻址存储单元。 如果有足够的空间,则立即在结构中紧随另一个位字段后面的位字段将被打包到同一单元的相邻位中。
因此,我相信上面的成员b应该已经被打包到为成员a分配的存储单元中,导致总大小为4个字节的结构体。
当使用两个成员相同的类型或一个是unsigned而另一个是signed时,GCC会正确地进行打包,但是类型unsigned和_Bool似乎对于GCC来说过于不同以处理它们正确。
有人可以确认我对标准的解释是否正确,并且这确实是一个GCC错误吗?
我也对解决方法感兴趣(某些编译器开关,pragma,__attribute__ ...)。
我正在使用gcc 4.7.0和-std=c11(尽管其他设置显示相同的行为)。
struct S {
unsigned a : 4;
_Bool b : 1;
};
由GCC布置为一个无符号的(4字节),其中使用了4位,后跟一个_Bool (4字节),其中使用了1位,总大小为8字节。
请注意,C99和C11特别允许_Bool作为位字段成员。 C11标准(可能也是C99)还在§6.7.2.1“结构和联合说明符” ¶11下规定:
实现可以分配任何足够大以容纳位字段的可寻址存储单元。 如果有足够的空间,则立即在结构中紧随另一个位字段后面的位字段将被打包到同一单元的相邻位中。
因此,我相信上面的成员b应该已经被打包到为成员a分配的存储单元中,导致总大小为4个字节的结构体。
当使用两个成员相同的类型或一个是unsigned而另一个是signed时,GCC会正确地进行打包,但是类型unsigned和_Bool似乎对于GCC来说过于不同以处理它们正确。
有人可以确认我对标准的解释是否正确,并且这确实是一个GCC错误吗?
我也对解决方法感兴趣(某些编译器开关,pragma,__attribute__ ...)。
我正在使用gcc 4.7.0和-std=c11(尽管其他设置显示相同的行为)。
__attribute__ ((packed))
可以应用于这里的成员,但与此问题无关(它会导致一个大小为4 + 1 = 5的结构体,即具有相同的问题)。 - ndkrempel