c++ - 我有一个数组 union 。从一个数组中读取一些元素并从另一个数组中读取其他元素是否可以?

标签 c++ c

<分区>

我有以下 union :

union PM_word {
    uint8_t  u8[8];
    uint16_t u16[4];
    uint32_t u32[2];
    uint64_t u64[1];
};

假设我初始化这个 union 的一个实例如下:

PM_word word;
word.u32[0] = 0;
word.u16[2] = 1;
word.u8[6] = 2;
word.u8[7] = 3;

如果我没理解错的话,尝试读取word.u32[1]是未定义的行为,因为word.u16word的元素。已设置的 u8 与其重叠。但是,读取 word.u32[0] 是否也是未定义的行为?

编辑: 也重新标记了 C++。如果 C 和 C++ 的语义在这个问题上不同,非常感谢关于 C 和 C++ 的答案。

最佳答案

相关C++标准引述:

[class.union]

In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended ([basic.life]). At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time. [... A special case regarding classes with common initial sequence, which does not apply to this example because the union has no members of class type ...]

...

When the left operand of an assignment operator involves a member access expression ([expr.ref]) that nominates a union member, it may begin the lifetime of that union member, as described below. For an expression E, define the set S(E) of subexpressions of E as follows:

  • If E is of the form A[B] and is interpreted as a built-in array subscripting operator, S(E) is S(A) if A is of array type, S(B) if B is of array type, and empty otherwise.

  • [... other cases are not relevant, because the quoted one applies ...]

In an assignment expression of the form E1 = E2 that uses either the built-in assignment operator ([expr.ass]) or a trivial assignment operator ([class.copy.assign]), for each element X of S(E1), if modification of X would have undefined behavior under [basic.life], an object of the type of X is implicitly created in the nominated storage; no initialization is performed and the beginning of its lifetime is sequenced after the value computation of the left and right operands and before the assignment. [ Note: This ends the lifetime of the previously-active member of the union, if any ([basic.life]). — end note  ]

这意味着在声明 word.u8[6] = 2; 之后,只有 word.u8 成员处于事件状态,所有其他 union 成员都处于非事件状态.在最后一条语句word.u8[7] = 3;之后,只有word.u8[6]word.u8[7]有初始化值。

不活跃成员的生命周期已经结束。以下是关于是否可以读取它们的值的相关规则:

[basic.life]

Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. ... The program has undefined behavior if:

  • the glvalue is used to access the object, or
  • ...

所以,是的。访问非事件成员将是 UB(除非该访问是一个赋值,或者在涉及类的公共(public)初始序列的特殊情况下,根据 [class.union])。

关于c++ - 我有一个数组 union 。从一个数组中读取一些元素并从另一个数组中读取其他元素是否可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57279499/

相关文章:

c++ - 合格类(class)成员

c++ - 在数组中存储类对象

c++ - RegQueryValueEx 不适用于发布版本,但在调试版本中工作正常

C: "read: Bad Address"和 "write: Bad Address"

c - ssize_t 在 Linux 中定义在哪里?

c - 用 fork() 填充数组

c++ - 如何使用 Visual Studio 2012 为 Windows XP 编译?

c++ - 如何在 boost tcp/udp 服务器中处理 control-c

c - 带指针的结构体定义

安卓NDK : keeping alive C++ objects