我看了http://en.cppreference.com/w/cpp/language/union:
联盟只有拥有其最大数据成员所需的大小。其他数据成员以与该最大成员的一部分相同的字节分配。该分配的细节是实现定义的,并且从未最近编写的联合成员中读取它的未定义行为。
我想知道为什么"它的未定义行为是从最近没有写过的工会成员那里读的#34;。
我想知道工会是否有填充来强制执行订单位,是否会读取最近编写的工会成员已定义的行为?
示例:
union {
uint8_t raw;
struct {
uint8_t a : 1;
uint8_t b : 2;
uint8_t padding : 5;
};
} U;
是否可以正确阅读U.raw?
提前致谢。
答案 0 :(得分:1)
在我使用的gcc x86编译器中,位字段恰好从LSB分配给MSB(如下所示)。 " raw"的布局也显示。
7 0
+---+---+---+---+---+---+---+---+
| padding | b | a |
+---+---+---+---+---+---+---+---+
7 0
+---+---+---+---+---+---+---+---+
| raw |
+---+---+---+---+---+---+---+---+
如果你将raw设置为01000101b(0x45),那么a == 1,b == 2和padding == 8
7 0
+---+---+---+---+---+---+---+---+
| padding | b | a |
+---+---+---+---+---+---+---+---+
0 1 0 0 0 1 0 1
但是,如果编译器将位字段从MSB分配给LSB怎么办?
7 0
+---+---+---+---+---+---+---+---+
| a | b | padding |
+---+---+---+---+---+---+---+---+
7 0
+---+---+---+---+---+---+---+---+
| raw |
+---+---+---+---+---+---+---+---+
现在,如果你将raw设置为01000101b(0x45),那么a == 0,b == 2和padding == 5.
7 0
+---+---+---+---+---+---+---+---+
| a | b | padding |
+---+---+---+---+---+---+---+---+
0 1 0 0 0 1 0 1
如果您了解编译器如何布局联合以及它如何分配位字段,您可以利用这一点,但请记住这不是可移植的。我在嵌入式软件领域工作,我们一直都在利用这一点。
答案 1 :(得分:1)
在标准C ++中,如果您访问的联盟成员与最近编写的联盟成员不同,则不会定义会发生什么。这与会员的内容无关。类型是,或他们的布局。
如果您的程序确实访问了其他成员,那么您依赖于特定于编译器的扩展。从理论上讲,如果编译器确实在C ++中定义了联合别名,那么它应该记录这一事实。