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

wir*_*bel 19 c struct principles c99 bit-fields

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

typedef struct Message_s {
     unsigned int flag : 1;
     unsigned int channel : 4;
     unsigned int signal : 11;
} Message;
Run Code Online (Sandbox Code Playgroud)

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

chq*_*lie 15

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

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

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

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

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

  • *"有些人甚至不信任编译器生成正确代码的能力."*[有时有充分理由](https://lwn.net/Articles/478657/). (5认同)

gsa*_*ras 8

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

bitfield-structs有一些限制:

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

资源

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


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

  • 虽然这些都是选择是否使用位域的相关评论,但它们并没有解决OP的问题,为什么其他程序员使用手工编码的位操作而不是位域来将多个字段打包成单个字. (6认同)
  • @chqrlie你说的是bitfields的缺点并不是程序员可能选择避免位域的原因吗?似乎很明显他们一定是. (3认同)
  • 我说如果他们编写显式代码来访问打包到单词中的值,那么它们已经具有您枚举的所有缺点,并且没有使用更简单的位域的优点,并且更不容易出错.正如我在回答中引用的那样,还有其他原因可以手动编码位操作而不是定义位域. (2认同)
  • 那么,#1点是手动按位操作可能是首选的正当理由.要点2-4适用于两者并且不回答问题. (2认同)
  • @Leushenko:字节顺序,字大小和对齐会影响位级别的结构布局.位字段添加了另一级别的实现定义行为,因为精确的按位布局是独立于字节顺序定义的实现. (2认同)