提问人:wimalopaan 提问时间:1/30/2023 最后编辑:Eric Postpischilwimalopaan 更新时间:1/31/2023 访问量:460
C/C++ 中的位字段:什么是保证的,什么是实现定义的?
Bit-Fields in C/C++: what is guaranteed, what is implementation-defined?
问:
https://en.cppreference.com/w/c/language/bit_field 读,以下结论正确吗?
- 相邻的位域之间没有填充(这在 C 标准的 6.7.2.1 中似乎有所不同)。
- 位域在存储单元中的放置是实现定义的。
- 位域内位的位置由实现定义。
(对于 C++,另请参阅:C++ 中位字段的特征。
答:
作为初步,没有问题标题引用的语言“C/C++”。C 和 C++ 是不同的语言,共享一个共同的子集。特别是,C 不是 C++ 的子集。
关于C语言,当前语言规范(目前为C17)提供的关于位域布局的所有细节都在第6.7.2.1/11-12段中。
以下结论正确吗?
- 相邻的位域之间没有填充(这在 C 标准的 6.7.2.1 中似乎有所不同)。
位字段不直接在结构中布局。C 实现在结构中为它们布置了“可寻址存储单元”,并在这些单元中布置了位字段。ASU 的尺寸和对齐要求未指定。
该规范确实指出,如果 ASU 中有足够的空间分配给一个位域,则紧随其后的位域将打包到同一 ASU 的相邻位中。这意味着这些位域之间没有填充位。但是,如果没有足够的空间,则由实现定义紧随的位域是跨越两个 ASU,还是将其所有位分配给一个单独的 ASU,在第一个 ASU 中保留未使用的(填充)位。此外,零宽度位域可用于强制将它后面的位域分配给新的 ASU,可能需要在前一个 ASU 中填充位。
此外,该规范对 ASU 之间是否存在填充字节没有任何说明。ASU 不需要大小一致或彼此具有相同的对齐要求,因此,即使在在这方面没有故意反常的实现中,有时它们之间也需要填充字节是合理的。
- 位域在存储单元中的放置是实现定义的。
该规范明确指出,ASU 中位域的顺序是实现定义的。这是从右到左与从左到右的意义。“订单”与“放置”并不完全相同,但我想这就是你的意思。
- 位域内位的位置由实现定义。
没有。这是一个表述问题,而不是布局问题,C17的相关段落是6.2.6.1/3-4:
存储在无符号位域和类型对象中的值应使用纯二进制表示法表示。
unsigned char
[...]存储在位字段中的值由 m 位组成,其中 m 是 为位字段指定的大小。对象表示是集合 M位,位域包含在可寻址存储单元中 拿着它。
脚注 49 澄清了“纯二进制表示法”的含义。位域表示的所有其他细节都是未指定或未定义的,不是实现定义的,这意味着您不能依赖它们被记录下来。
C++ 中的差异包括但不限于:
- C++ 正式批准比 C 更多的位字段声明类型。
- C++ 定义了一种机制,用于声明包含填充位的位字段,但 C 没有。
- 位域分配和对齐是用 C++ 定义的实现(而不是在 C 中指定)。
C++ 规范的相关部分是 [class-bit],当前草案规范中的 11.4.10。
上一个:C++ 中位字段的特征
评论