Union Bit Fields

时间:2016-03-28 04:29:16

标签: c++ c++11

我看了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?

提前致谢。

2 个答案:

答案 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 ++中定义了联合别名,那么它应该记录这一事实。