是否有理由避免使用位域结构成员?

时间:2017-09-03 08:56:52

标签: c struct c99 bit-fields principles

我早就知道C中有位字段,偶尔也会使用它们来定义密集的结构:

typedef struct Message_s {
     unsigned int flag : 1;
     unsigned int channel : 4;
     unsigned int signal : 11;
} Message;

当我阅读开源代码时,我经常会发现位掩码和位移操作,以便在手工滚动的位域中存储和检索这些信息。这是如此常见,我不认为作者不知道位字段语法,所以我想知道是否有理由通过位掩码滚动位字段并转移自己的操作而不是依靠编译器生成用于获取和设置此类位字段的代码。

4 个答案:

答案 0 :(得分:15)

  

为什么其他程序员使用手工编码的位操作而不是位域来将多个字段打包成一个字?

这个答案是基于意见的,因为问题非常开放:

  • 许多程序员不知道位域的可用性或不确定它们的可移植性和精确语义。有些人甚至不信任编译器生成正确代码的能力。他们更喜欢编写他们理解的显式代码。

    正如Cornstalks评论的那样,这种态度植根于现实生活中as explained in this article

  • Bitfield的实际存储器布局是实现定义的:如果存储器布局必须遵循精确的规范,则不应使用位域,并且可能需要手动编码位操作。
  • 在签名类型的位域中处理签名值是实现定义的。如果将有符号值打包到一系列位中,则对访问函数进行手动编码可能更可靠。

答案 1 :(得分:8)

  

是否有理由避免使用位域结构?

bitfield-structs有一些限制:

  1. 位字段导致不可移植的代码。此外,位字段长度对字大小有很高的依赖性。
  2. 由于不可寻址,无法读取(使用scanf())并在位字段上使用指针。
  3. 位字段用于将更多变量打包到较小的数据空间中,但会导致编译器生成其他代码来操作这些变量。这导致空间和时间复杂性的增加。
  4. sizeof()运算符不能应用于位字段,因为sizeof()产生的结果以字节为单位而不是位。
  5. Source

    所以你是否应该使用它们取决于。阅读Why bit endianness is an issue in bitfields?

    中的更多内容

    PS:When to use bit-fields in C?

答案 2 :(得分:4)

没有理由这样做。位域是有用和方便的。它们在嵌入式项目中很常见。某些架构(如ARM)甚至有特殊的指令来操作位域。

只需比较代码(并编写函数foo1的其余部分) https://godbolt.org/g/72b3vY

答案 3 :(得分:0)

在许多情况下,能够对单词中的各个位组进行寻址,或者将单词作为一个单元进行操作是很有用的。该标准目前不提供 任何实用和便携的方式来实现这种功能。如果编写代码以使用位域,并且稍后有必要将多个组作为一个单词进行访问,那么在没有使用位字段重新编写所有代码或禁用基于类型的别名优化(使用类型双关)的情况下,没有很好的方法来适应这种情况。并希望一切按预期布置。

使用移位和掩码可能不够优雅,但是直到C提供了将一个左值中的明确指定的位序列作为另一个左值处理的方法,它通常是确保代码的最佳方法将适应以满足需求。