这个位域会以我期望的方式工作吗?

时间:2011-10-13 14:02:53

标签: c struct unions bit-fields

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

我希望这个问题符合SO的格式。

我的问题是我的结构(后面的定义)是否会以我期望的方式实际执行。这是我提出的定义,然后我将讨论我想要的内容:

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__指令)。

你可以告诉我的目的:根据'state'字段的值,我想将剩余的30位用于不同的目的。它们应该是ID号,或者是各种缓冲区的2元组索引。 并且,MyStruct的每个实例最多应该包含5个字节。

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

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

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

主要是我正在寻找关于这是否是“正确的事情”的意见。换句话说,我在这里滥用了bitfields / union的想法吗?如果你要成为这个代码的维护者,看到这个时你会惊恐万分吗?或者,您是否希望看到整个数据对象以uint32_t类型存储并通过屏蔽和移位进行操作?

1 个答案:

答案 0 :(得分:4)

当任何unionstruct的开头将在边界上对齐时,您无法以这种方式将所有数据整合为32位。你应该反过来封装你的unionstruct,如下所示(为了便于阅读,删除了属性):

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