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

我一直在读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; 

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

由于任何unionstruct的开头都将在边界上对齐,因此您不能以32位方式将所有数据拟合。 你应该将你的unionstruct ,如下所示(为了便于阅读,删除了属性):

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