1

如果我有 16 位代表 3 对值,每对 5 位长,另外一个 1 位值,完全按照这个顺序,使用位域来描述它是否安全?ANSI C是否保证位将完全按照我指定的顺序?

struct {
    unsigned v1 : 5;
    unsigned v2 : 5;
    unsigned v3 : 5;
    unsigned v4 : 1;
} test;

如果没有,是否有任何其他数据结构可以用来表示这一点?还是我应该只存储两个 8 位char并以编程方式对其进行操作以确保可移植性?

4

3 回答 3

4

我能找到的相关报价是 6.7.2.1(1),来自 C99:

实现可以分配任何大到足以容纳位域的可寻址存储单元。如果有足够的空间剩余,紧跟在结构中另一个位域之后的位域将被打包到同一单元的相邻位中。如果剩余空间不足,则将不适合的位域放入下一个单元还是与相邻单元重叠是实现定义的。单元内位域的分配顺序(高位到低位或低位到高位)是实现定义的。未指定可寻址存储单元的对齐方式。

我认为这unsigned实际上不是“基础单元”类型,而是它只是位域声明本身的一部分:T : n表示“采用n位类型T”。真正的问题是是否需要选择一个“大”单元来实现。例如,它可以通过将单位设为 a 来使用三个字节char;一个为v1,一个为v2,最后一个为v3, v4。或者它可以使单元成为 16 位整数,在这种情况下,它只需要使用一个单元。

但是,正如您所指出的,单元内位字段的顺序是未指定的。C 中数据的原子单位是地址,位域没有地址。可以保证结构成员的地址按其声明的顺序增加,但您不能对位域(仅关于它们的基础单元)做出这样的声明。

于 2012-06-05T02:38:15.300 回答
1

您可以使用uint16_tfrom 类型stdint.h,它保证是无符号 16 位数量的类型同义词。如果您担心字节顺序,它会变得更加复杂。

于 2012-06-05T02:36:11.573 回答
0

除了位字段的实现定义方面,您可能还需要添加一个 pragma 或其他编译器指令来告诉编译器不要插入任何填充位。

这是我刚刚写的关于如何使用位域从字节值中提取一些位的答案。当我写这篇文章时,我发现我需要添加#pragma pack(1),否则我的位字段不适合单个字节。

在 C 中访问 c​​har 中的位

该答案还显示了如何使用 aunion让您以完整字节或位字段的形式访问数据。您可以使用相同的技术以短整数或位字段的形式访问数据。

于 2012-06-05T03:33:15.493 回答