将 union 与结构内的位字段结合使用的正确语法
Proper syntax for using union with bit fields inside a struct
我有以下一系列结构。
struct FooWord1
{
unsigned int Fill : 8;
unsigned int someData1 : 18;
unsigned int someData2 : 6;
};
struct FooWord2
{
unsigned int Fill : 8;
union
{
unsigned int A_Bit : 1;
unsigned int B_Bit : 1;
};
unsigned int someData3 : 23;
};
struct Foo_Data
{
FooWord1 fooWord1;
FooWord2 fooWord2;
FooWord3 fooWord3; // similar to FooWord1
FooWord4 fooWord4; // similar to FooWord1
FooWord5 fooWord5; // similar to FooWord1
};
Foo_Data fooArray[SIZE];
数据从网络消息逐字节复制到 fooArray
。如果我们不使用带 1 位字段的联合(A_bit
和 B_bit
),我们会在 someData3
中得到我们期望的数据,但是一旦我们放入联合,单词得到 "off" 2 个单词。
这里要用union,因为这些结构是针对不同类型的消息使用的,但是A_Bit
和B_Bit
对于不同的消息来说意义是不同的。我们可以只使用注释,但最好用代码来完成。
我做错了什么?
你可以试试这个:
struct FooWord2
{
union
{
struct
{
unsigned int Fill : 8;
unsigned int A_Bit : 1;
unsigned int someData3 : 23;
};
struct
{
unsigned int : 8;
unsigned int B_Bit : 1;
};
};
};
需要说明:根据这个answer,匿名结构不是C++标准,而是对. GCC 允许,MSVC——据我所知——也是。 LLVM?不确定,但通常接近 GCC,也会这样认为。
在符合标准的库中,他们经常使用宏来获得正确的效果,就像这样:
struct FooWord2
{
unsigned int Fill : 8;
unsigned int A_Bit : 1;
unsigned int someData3 : 23;
};
#define B_Bit A_Bit
只是解释一下:用你的原始代码,你得到了这个效果:
- 填充开始一个新的位域
- 联合是另一种数据类型,所以前面的位字段完成了
- 在 union 内部,一个新的位字段从这里开始我不确定这是否会创建一个位或可能是一个包含两个条目的位字段。也许任何人都可以阐明标准规定的内容...
- 关闭联合,位域也完成了。
- someData3 然后开始一个新的位域
因此您要避免偏移。
答案就在对原问题的评论中。 Fill
、union
和 someData3
都将以单独的词结束,因为 union
在结构中开始了一个新词。
我有以下一系列结构。
struct FooWord1
{
unsigned int Fill : 8;
unsigned int someData1 : 18;
unsigned int someData2 : 6;
};
struct FooWord2
{
unsigned int Fill : 8;
union
{
unsigned int A_Bit : 1;
unsigned int B_Bit : 1;
};
unsigned int someData3 : 23;
};
struct Foo_Data
{
FooWord1 fooWord1;
FooWord2 fooWord2;
FooWord3 fooWord3; // similar to FooWord1
FooWord4 fooWord4; // similar to FooWord1
FooWord5 fooWord5; // similar to FooWord1
};
Foo_Data fooArray[SIZE];
数据从网络消息逐字节复制到 fooArray
。如果我们不使用带 1 位字段的联合(A_bit
和 B_bit
),我们会在 someData3
中得到我们期望的数据,但是一旦我们放入联合,单词得到 "off" 2 个单词。
这里要用union,因为这些结构是针对不同类型的消息使用的,但是A_Bit
和B_Bit
对于不同的消息来说意义是不同的。我们可以只使用注释,但最好用代码来完成。
我做错了什么?
你可以试试这个:
struct FooWord2
{
union
{
struct
{
unsigned int Fill : 8;
unsigned int A_Bit : 1;
unsigned int someData3 : 23;
};
struct
{
unsigned int : 8;
unsigned int B_Bit : 1;
};
};
};
需要说明:根据这个answer,匿名结构不是C++标准,而是对. GCC 允许,MSVC——据我所知——也是。 LLVM?不确定,但通常接近 GCC,也会这样认为。
在符合标准的库中,他们经常使用宏来获得正确的效果,就像这样:
struct FooWord2
{
unsigned int Fill : 8;
unsigned int A_Bit : 1;
unsigned int someData3 : 23;
};
#define B_Bit A_Bit
只是解释一下:用你的原始代码,你得到了这个效果:
- 填充开始一个新的位域
- 联合是另一种数据类型,所以前面的位字段完成了
- 在 union 内部,一个新的位字段从这里开始我不确定这是否会创建一个位或可能是一个包含两个条目的位字段。也许任何人都可以阐明标准规定的内容...
- 关闭联合,位域也完成了。
- someData3 然后开始一个新的位域
因此您要避免偏移。
答案就在对原问题的评论中。 Fill
、union
和 someData3
都将以单独的词结束,因为 union
在结构中开始了一个新词。