我一直在读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
类型存储并通过屏蔽和移位进行操作?
答案 0 :(得分:4)
当任何union
或struct
的开头将在边界上对齐时,您无法以这种方式将所有数据整合为32位。你应该反过来封装你的union
和struct
,如下所示(为了便于阅读,删除了属性):
typedef struct MyStruct {
union {
struct {
unsigned state : 2;
unsigned id : 30;
}
struct {
unsigned /* unused */ : 2;
unsigned bufferAIdx : 16;
unsigned bufferBIdx : 14;
};
};
};