c - 看不懂C标准的位域描述

标签 c

"Whether a field may overlap a word boundary is implementation-defined. Fields need not be named; unnamed fields (a colon and width only) are used for padding. The special width 0 may be used to force alignment at the next word boundary."

- The C programming Language [2e] by Kernighan & Ritchie [Section 6.9, p.150]

我无法获取这些行。你能解释一下吗?

最佳答案

"whether a field may overlap a word bounday is implementation - defined.

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

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] ... [2] [1] [0]

如果我们有一个结构:

struct X
{
    int a : 30;
    int b : 4;
};

然后编译器可能会选择将字段 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

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

fields need not be named; unnamed fields ( a colon and width only) are used for padding.

如果我们改变了我们之前的结构,我们可以明确地要求一个间隙:

struct X
{
    int a : 30;
    int   : 2;  // unnamed field
    int b : 4;
};

这就是说“在 a 和 b 之间保留 2 位 - 它们不需要标识符(名称),因为我永远不会问它们里面有什么,也不需要问它们的值是否改变”。但是,您不必将其设置为 2 以便 30 + 2 == 32(我们的字长)...您可以在任何您喜欢的地方要求任何您喜欢的差距。如果您正在处理来自某些硬件设备的值,并且您知道某些位是什么但不知道其他位是什么,或者您只是不需要使用其中的一些位,这可能很有用 - 您可以将它们不命名以记录您不感兴趣,同时仍然让编译器将所需偏移处的命名位字段空间放入与硬件使用相对应的必要字中。

the special width 0 may be used to force alignment at the next word boundary."

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

struct X
{
    int a : 30;
    int   : 0;  // unnamed field
    int b : 4;
};

...编译器会为我们计算出 2。这样,如果我们将 a 更改为其他大小,或者最终针对 64 位字大小进行编译,编译器将自动调整为适当的行为,而无需手动更正未命名字段。

关于c - 看不懂C标准的位域描述,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3093272/

相关文章:

c - SIGSTOP/SIGCONT POSIX 行为

c++ - 在指定 C++ 异常和 pthread 取消的交互方面有什么进展吗?

c - 数组给出垃圾值

c - 文件无法识别 : File format not recognized

c - 异或/或运算符?

c - 尝试将值转换为 C 中的 2s 补码

c - 通过构建尾部优化链表中的一个特例

c - 这个变量存储在c的内存中的什么位置?

c - 为什么这个分配在堆栈而不是堆上?

c - epoll消息服务器