我必须在跨越多个DWORDS的位域中编程独立位。我目前正在使用如下结构
typedef struct _myStruct
{
union
{
struct
{
DWORD field1 : 16
DWORD field2 : 8
DWORD field3 : 8
};
DWORD value0;
};
union
{
struct
{
DWORD field4 : 32;
}
DWORD value1;
};
} myStruct;
我这样做是为了让程序员可以直接访问独立的字段,而不记得相应的DWORD,即myStruct.field1
等。
这在Visual Studio中运行良好,但是当我使用未命名的结构和联合时,GCC会抱怨。为了纠正这一点,我尝试命名联合和结构如下:
union _DW0
{
struct _BF
{
DWORD field1 : 16
DWORD field2 : 8
DWORD field3 : 8
} BF;
DWORD value0;
} DW0;
但是现在访问并不是程序员友好的...即尝试编程的人必须记住每个字段属于哪个DWORD。例如:myStruct.DW0.field1
有没有办法解决这个问题?
答案 0 :(得分:1)
Bitfields本质上是不可移植的。当您编写DWORD field1 : 16;
时,标准不会确定field1
是否应该具有结构的高16位或低16位。另一方面,如果你使用正确的类型和联合(在你的情况下就足够了,因为你的所有位域都与大多数平台上的类型相匹配),那么可以是可移植的。
使用C ++ 11类型(您也可以使用适合您平台的类型的库):
union {
struct {
uint16_t _1;
uint8_t _2;
uint8_t _3;
} field;
uint32_t value;
};
// ...
答案 1 :(得分:0)
匿名工会通常没问题,但结构需要有一个名字。您可以使用它从语法中删除一个级别的“点”。
但是,如果您需要通过命名结构成员单独(作为位域)和(作为DWORDS)访问字段,则必须使用稍微混乱的语法。这种用例需要联合,这需要内部结构,这会导致问题。您总是可以隐藏getter / setter函数背后的所有混乱语法,但如果结构很大,那么该方法将无法维护。
以下是您可以考虑的替代方案:
typedef struct
{
// DWORD 0
DWORD field1 : 16;
DWORD field2 : 8;
DWORD field3 : 8;
// DWORD 1
DWORD field4 : 32;
} bitfield_struct;
这只能为您提供位域级访问,但语法更清晰。如果需要,您仍然可以访问DWORD级别的数据:
bitfield_struct foo;
DWORD* bar = (DWORD*)&foo;
bar[0] = ...;
bar[1] = ...;
如果您通常通过位域访问数据并且很少通过DWORD访问它,那么这可能是一个可接受的解决方案。