这个位域会像我期望的那样工作吗? [英] Will this bitfield work the way I expect?
问题描述
我一直在阅读 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?
推荐答案
由于任何 union
或 struct
的开头都将在边界上对齐,因此无法容纳所有你的数据以这种方式 32 位.您应该反过来封装 union
和 struct
,如下所示(为了可读性而删除了属性):
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屋!