简体   繁体   English

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

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

I long knew there are bit-fields in C and occasionally I use them for defining densely packed structs: 我早就知道C中有位字段,偶尔我会用它们来定义密集的结构:

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

When I read open source code, I instead often find bit-masks and bit-shifting operations to store and retrieve such information in hand-rolled bit-fields. 当我阅读开源代码时,我经常会发现位掩码和位移操作,以便在手工滚动的位域中存储和检索这些信息。 This is so common that I do not think the authors were not aware of the bit-field syntax, so I wonder if there are reasons to roll bit-fields via bit-masks and shifting operations your own instead of relying on the compiler to generate code for getting and setting such bit-fields. 这是如此常见,我不认为作者不知道位字段语法,所以我想知道是否有理由通过位掩码滚动位字段并转移自己的操作而不是依靠编译器生成用于获取和设置此类位字段的代码。

Why other programmers use hand-coded bit manipulations instead of bitfields to pack multiple fields into a single word? 为什么其他程序员使用手工编码的位操作而不是位域来将多个字段打包成一个字?

This answer is opinion based as the question is quite open: 这个答案是基于意见的,因为这个问题非常开放:

  • Many programmers are unaware of the availability of bitfields or unsure about their portability and precise semantics. 许多程序员不知道位域的可用性或不确定它们的可移植性和精确的语义。 Some even distrust the compiler's ability to produce correct code. 有些人甚至不信任编译器生成正确代码的能力。 They prefer to write explicit code that they understand. 他们更喜欢编写他们理解的显式代码。

    As commented by Cornstalks, this attitude is rooted in real life experience as explained in this article . 正如Cornstalks评论的那样,这种态度植根于本文所解释的现实生活体验。

  • Bitfield's actual memory layout is implementation defined: if the memory layout must follow a precise specification, bitfields should not be used and hand-coded bit manipulations may be required. Bitfield的实际存储器布局是实现定义的:如果存储器布局必须遵循精确的规范,则不应使用位域,并且可能需要手动编码的位操作。
  • The handing of signed values in signed typed bitfields is implementation defined. 在签名类型的位域中处理签名值是实现定义的。 If signed values are packed into a range of bits, it may be more reliable to hand-code the access functions. 如果将有符号值打包到一系列位中,则对访问函数进行手动编码可能更可靠。

Are there reasons to avoid bitfield-structs? 是否有理由避免使用位域结构?

bitfield-structs come with some limitations: bitfield-structs有一些限制:

  1. Bit fields result in non-portable code. 位字段导致不可移植的代码。 Also, the bit field length has a high dependency on word size. 此外,位字段长度对字大小具有高依赖性。
  2. Reading (using scanf() ) and using pointers on bit fields is not possible due to non-addressability. 由于不可寻址,因此无法读取(使用scanf() )并在位字段上使用指针。
  3. Bit fields are used to pack more variables into a smaller data space, but cause the compiler to generate additional code to manipulate these variables. 位字段用于将更多变量打包到较小的数据空间中,但会使编译器生成其他代码来操作这些变量。 This results in an increase in both space as well as time complexities. 这导致空间和时间复杂性的增加。
  4. The sizeof() operator cannot be applied to the bit fields, since sizeof() yields the result in bytes and not in bits. sizeof()运算符不能应用于位字段,因为sizeof()以字节而不是以位为单位产生结果。

Source 资源

So whether you should use them or not depends. 所以你是否应该使用它们取决于。 Read more in Why bit endianness is an issue in bitfields? 阅读更多内容为什么bit endianness是bitfields中的一个问题?


PS: When to use bit-fields in C? PS: 何时在C中使用位域?

There is no reason for it. 没有理由。 Bitfields are useful and convenient. 位域是有用和方便的。 They are in the common use in the embedded projects. 它们在嵌入式项目中很常见。 Some architectures (like ARM) have even special instructions to manipulate bitfields. 某些架构(如ARM)甚至有特殊的指令来操作位域。

Just compare the code (and write the rest of the function foo1) https://godbolt.org/g/72b3vY 只需比较代码(并编写函数foo1的其余部分) https://godbolt.org/g/72b3vY

In many cases, it is useful to be able to address individual groups of bits within a word, or to operate on a word as a unit. 在许多情况下,能够对一个字内的各个位组进行寻址,或者将一个字作为一个单元进行操作是很有用的。 The Standard presently does not provide any practical and portable way to achieve such functionality. 该标准目前没有提供任何实用和便携的方式来实现这种功能。 If code is written to use bitfields and it later becomes necessary to access multiple groups as a word, there would be no nice way to accommodate that without reworking all the code using the bit fields or disabling type-based aliasing optimizations, using type punning, and hoping everything gets laid out as expected. 如果编写代码以使用位域,并且稍后有必要将多个组作为一个单词进行访问,那么在没有使用位字段重新编写所有代码或禁用基于类型的别名优化(使用类型双关)的情况下,没有很好的方法来适应这种情况。并希望一切都按预期布局。

Using shifts and masks may be inelegant, but until C provides a means of treating an explicitly-designated sequence of bits within one lvalue as another lvalue, it is often the best way to ensure that code will be adaptable to meet needs. 使用移位和掩码可能是不优雅的,但是直到C提供了将一个左值内的明确指定的位序列视为另一个左值的方法,它通常是确保代码适应以满足需要的最佳方式。

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

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