不理解C标准中的位字段描述

ash*_*hna 3 c

"字段是否可以重叠单词bounday是实现定义的.字段不需要命名;未命名的字段(仅冒号和宽度)用于填充.特殊宽度0可用于强制在下一个字边界处对齐. "

我无法得到这些线条.你能解释一下吗?

Ton*_*roy 6

"字段是否可以重叠单词bounday是实现定义的.

考虑两个内存字,其中字大小为32位:

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] ... [2] [1] [0]
Run Code Online (Sandbox Code Playgroud)

如果我们有一个结构:

struct X
{
    int a : 30;
    int b : 4;
};
Run Code Online (Sandbox Code Playgroud)

然后编译器可能会选择放置字段b,因此部分位于每个单词中,或者它可能会留下间隙,以便所有b都落在第二个单词内:

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] [28] ... [2] [1] [0]
a--------------------a b-----------------b
OR
a--------------------a    GAP    b-----------------b
Run Code Online (Sandbox Code Playgroud)

为什么会留下GAP?因为当它想要读取或写入b时,它只需要在内存中使用一个字 - 这通常更快更简单,需要更少的CPU指令.

字段不需要命名; 未命名的字段(仅冒号和宽度)用于填充.

如果我们改变了早期的结构,我们可以明确地要求一个空白:

struct X
{
    int a : 30;
    int   : 2;  // unnamed field
    int b : 4;
};
Run Code Online (Sandbox Code Playgroud)

这就是说"在a和b之间留下2位 - 它们不需要标识符(名称),因为我永远不会问它们中有什么,或者需要询问它们的值是否被改变".但是,你不必只是为了30 + 2 == 32(我们的字号)......你可以随心所欲地找到你喜欢的任何空白.如果您正在处理来自某些硬件设备的值,并且您知道某些部分是什么而不是其他部分,或者您只是不需要使用其中的某些部分,那么这可能很有用 - 您可以将它们保留为未命名的文档你仍然不感兴趣,同时仍然在编译空间中将所需的偏移量中的命名位字段转换为与硬件用法相对应的字.

特殊宽度0可用于强制在下一个字边界处对齐."

这只意味着编译器可以计算部分填充的字中剩余的位数,并跳到下一个字的开头.正如我们通过在上面添加一个2比特字段确保b以一个新单词开始(假设我们知道a是30位且字大小为32),我们可以......

struct X
{
    int a : 30;
    int   : 0;  // unnamed field
    int b : 4;
};
Run Code Online (Sandbox Code Playgroud)

...编译器会为我们解决2.这样,如果我们将a更改为其他大小,或者最终编译为64位字大小,编译器将静默调整到适当的行为,而无需手动更正未命名的字段.