根据规格,我们拥有
一个实现可以分配任何足够大的可寻址存储单元来容纳一个位,
领域。如果仍有足够的空间,则一个位域紧跟在一个
结构应打包到同一单元的相邻位中。如果空间不足,
是将不合适的位字段放入下一个单元还是与相邻单元重叠
实现定义的。单位内位域的分配顺序(从高到高)
低阶或从低阶到高阶)是实作定义。的对齐
未指定可寻址存储单元。
因此,实际行为取决于编译器为位字段选择的大小分配单位,以及它是否允许字段跨越多个分配单位。该选择是实现定义的,但是一个常见的实现是使用声明的位字段类型作为分配单位,并且不允许跨越分配单位边界。因此,当您使用(unisgned)char时,它将使用8位分配单元。这意味着不能将两个位域组合为一个字节(7 + 7> 8和7 + 2> 8),因此最终将占用3个分配单位(字节),然后将其舍入到4以进行对齐加上工会的空缺。
将位域大小更改为6时,现在第二个和第三个位域可以容纳一个字节(6 + 2 = 8),因此它仅占用两个分配单元。
当您将位域类型更改为short
时,它使用16位分配单元,因此所有3个位域都可以容纳一个分配单元。
,
使用struct
和union
时要注意几点。最常见的是,慷慨地填充字段以使其与CPU的字长对齐。
struct {
char c1;
char c2;
} s1;
似乎应该是两个字节的结构,但是令人惊讶的是sizeof (s1)
通常不是2,而是4甚至8。甚至在1980年代使用16位计算机的情况下也是这样。
这是因为C和C ++编译器会将结构的每个char
元素对齐到两个字节或四个字节的边界。我还没有看到结构元素与8字节边界对齐,但是还没有64位体系结构这么需要-
解决方案是调用一个编译选项来“打包结构”。既可以在编译器命令行上完成此操作,也可以在结构声明之前包含一个合适的#pragma选项:
#pragma pack(1) // this particular syntax is valid for many compilers
struct {
char c11;
char c12;
} s2;
#pragma pack(4)
,
取自标准(n4835):
11.4.9位字段[class.bit]
1 [...]在类对象中分配位字段是由实现定义的。比特字段的对齐方式是由实现定义的。比特字段打包到某个可寻址的分配单元中。 [注意:位域跨越了某些机器上的分配单元,而不是在其他机器上。在某些机器上,位字段是从右到左分配的,在其他机器上是从左到右分配的。 —尾注]
如您所见,大小和对齐方式是实现定义的。因此,您可能会在其他编译器/平台上获得预期的行为,但是在您的编译器/平台上,将得到与预期不同的结果。
本文链接:https://www.f2er.com/2592671.html