这个位域会像我期望的那样工作吗? [英] Will this bitfield work the way I expect?

查看:30
本文介绍了这个位域会像我期望的那样工作吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读 C 中的位域,C 标准如何不强制机器字中字段的任何特定顺序,等等.

I've been doing some reading about bitfields in C, how the C standard doesn't enforce any particular ordering of the fields in a machine word, and so on.

我希望这个问题适合 SO 的格式.

I hope this question appropriately fits the format of SO.

我的问题是我的结构(定义如下)是否会按照我期望的方式实际执行.这是我想出的定义,然后我会讨论我想要的:

My question is whether my struct (definition following) will actually perform in the way I expect. Here's the definition I came up with, and then I'll discuss what I want:

typedef enum {
   STATE_ONE,
   STATE_TWO,
   STATE_THREE,
   STATE_FOUR
} __attribute__ ((packed)) State;

typedef struct MyStruct {
   // One of State enum (maximum of 4 states).
   unsigned state : 2;

   // Remaining 30 bits are used differently depending on 'state'.
   union {
      // If 'state' is STATE_ONE (0), the remaining bits are an ID number.
      unsigned id : 30;

      /* 
       * For all other states, the remaining bits are the 2-tuple:
       *  (buffer A index, buffer B index).
       */
      struct {
         unsigned bufferAIdx : 16;
         unsigned bufferBIdx : 14;
      } __attribute__ ((packed)) index;
   } __attribute__ ((packed));
} __attribute__ ((packed)) MyStruct;

(这是针对 gcc 的,因此是 __attribute__ 指令).

(This is for gcc, thus the __attribute__ directives).

您可能知道我要做什么:根据状态"字段的值,我想将剩余的 30 位用于不同的目的.它们应该是一个 ID 号,或者是一个 2 元组的索引到各种缓冲区.而且,MyStruct 的每个实例最多应容纳 5 个字节.

You can probably tell what I'm going for: depending on the value of the 'state' field I want to use the remaining 30 bits for different purposes. They should either be an ID number, or a 2-tuple of indices into various buffers. And, each instance of MyStruct should fit into a maximum of 5 bytes.

所以我想要做的就是达到这个效果:

So what I want to be able to do is something to this effect:

MyStruct a, b;
a.state = STATE_ONE;
a.id = 123456;

b.state = STATE_THREE;
b.index.bufferAIdx = 6;
b.index.bufferBIdx = 2;

主要是我在寻找关于这是否是正确的事情"的意见.换句话说,我在这里滥用了位域/联合的想法吗?如果你打算成为这段代码的维护者,你会不会害怕看到这个?或者,您是否希望看到以 uint32_t 类型存储并通过屏蔽和移位进行操作的整个数据对象?

Mainly I'm looking for input on whether this is "the right thing" to do. In other words, am I misusing the ideas of bitfields/unions here? If you were going to be a maintainer of this code, would you cringe in horror upon seeing this? Or, would you prefer to see the whole data object stored in a uint32_t type and manipulated via masking and shifting?

推荐答案

由于任何 unionstruct 的开头都将在边界上对齐,因此无法容纳所有你的数据以这种方式 32 位.您应该反过来封装 unionstruct,如下所示(为了可读性而删除了属性):

As the beginning of any union or struct will be aligned on a boundary, you cannot fit all your data in 32 bits this way. You should encapslulate your union and struct the other way round, as follows (attributes removed for readability):

typedef struct MyStruct {
   union {
      struct {
         unsigned state :  2;
         unsigned id    : 30;
      }
      struct {
         unsigned /* unused */ :  2; 
         unsigned bufferAIdx   : 16;
         unsigned bufferBIdx   : 14;
      };
   };
};

这篇关于这个位域会像我期望的那样工作吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆