位域的 GCC 实现中的一个错误

2023-11-27

在 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“结构和联合说明符”¶11 中规定:

实现可以分配任何足够大以容纳位字段的可寻址存储单元。如果剩余足够的空间,则结构中紧跟在另一个位字段之后的位字段应被打包到同一单元的相邻位中。

所以我相信这位会员b上面应该已经被打包到为成员分配的存储单元中a,产生总大小为 4 字节的结构。

GCC 行为正确,并且当两个成员使用相同类型时,或者当其中一个成员使用相同类型时,确实会发生打包。unsigned和另一个signed,但是类型unsigned and _BoolGCC 似乎认为它们过于独特,无法正确处理它们。

有人可以确认我对标准的解释,并且这确实是一个 GCC 错误吗?

我也对解决方法感兴趣(一些编译器开关、pragma、__attribute__...).

我正在使用 gcc 4.7.0-std=c11(尽管其他设置显示相同的行为。)


所描述的行为与 C99 和 C11 标准不兼容,但提供了与 MSVC 编译器(具有不寻常的结构打包行为)的二进制兼容性。

幸运的是,它可以在代码中禁用__attribute__((gcc_struct))应用于结构体,或使用命令行开关-mno-ms-bitfields(参见文档).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

位域的 GCC 实现中的一个错误 的相关文章

随机推荐