位域中宽度为零的连续未命名域不会改变结构的大小

问题描述 投票:0回答:2

这是一个

struct
.

struct {
   unsigned int a : 8;
   unsigned int   : 0;
   unsigned int f : 1;
} A;

sizeof
struct
A
这里是8个字节。我明白那个。但是现在,如果我再放一个宽度为零的未命名字段,如下所示,

struct {
   unsigned int a : 8;
   unsigned int   : 0;
   unsigned int   : 0;
   unsigned int f : 1;
} A;

现在,

sizeof
struct
A
仍然是 8 个字节。当我看到参考资料时,它说使用宽度为 0 的未命名字段会强制下一个字段与下一个整数对齐。所以,
sizeof
结构
A
在这里应该是12个字节。或者将两个连续的未命名字段宽度设置为 0 是否没有达到预期的效果?

c bit-fields
2个回答
4
投票

C17 6.7.2.1/12:

作为一种特殊情况,宽度为 0 的位域结构成员表示没有进一步的位域被打包到前一个位域所在的单元中, 如果有的话,被放置了。

所以

: 0
的意思是“停止在前一个位域中打包位”。这并不意味着“开始在新的位域中打包位”。

在第一个零位字段的情况下,这意味着不应将更多位打包到存储

a : 8
的前一个位中。如果您添加另一个零位字段,那么编译器仍然将
a : 8
视为前一个。

作为旁注,编译器可以在位域成员之间随意放置填充字节,具体取决于标准称为“可寻址存储单元”的内部大小。所以你永远不能假设这个结构的大小是 guaranteed 在 32 位系统上是 8。


3
投票

当我看到参考资料时,它说使用宽度为 0 的未命名字段会强制下一个字段与下一个整数对齐。

当你引用一些文件时,无论你的“引用”是什么,你都应该给出该文件的书目引用,如果有的话,一个 URL,以便其他人可以检查该文件。

在这种情况下,您的“参考”是错误的。为位域宽度指定零并不意味着前进到“下一个”整数或“下一个”存储单元。根据 C 2018 6.7.2.1 12,这意味着“没有进一步的位域被打包到放置前一个位域(如果有的话)的[存储]单元中。”因此,第一个零宽度位域表示不再向当前存储单元中填充任何字段,第二个零宽度位域也表示不再向当前存储单元中填充任何字段。不代表跳到另一个存储单元,所以宽度为零的两个字段不会跳过超过一个字段

此外,用于存储位域的存储单元本身并不是“整数”。 C 2018 6.7.2.1 11 说“一个实现可以分配任何大到足以容纳位域的可寻址存储单元......”因此 C 实现使用其选择的字节分组来保存位域。

© www.soinside.com 2019 - 2024. All rights reserved.