繁体   English   中英

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

[英]Are there reasons to avoid bit-field structure members?

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

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

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

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

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

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

    正如Cornstalks评论的那样,这种态度植根于本文所解释的现实生活体验。

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

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

bitfield-structs有一些限制:

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

资源

所以你是否应该使用它们取决于。 阅读更多内容为什么bit endianness是bitfields中的一个问题?


PS: 何时在C中使用位域?

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM