C/C++ 联合和未定义的行为

C/C++ unions and undefined behaviour

下面是未定义的行为吗?

 union {
   int foo;
   float bar;
 } baz;

 baz.foo = 3.14 * baz.bar;

我记得在两个序列点之间从同一底层内存写入和读取是UB,但我不确定。

I remember that writing and reading from the same underlying memory between two sequence points is UB, but I am not certain.

读取和写入同一表达式中的同一内存位置不会调用未定义的行为,除非该位置在两个序列点之间被修改多次,或者副作用相对于使用该值的值计算是未排序的在同一地点。

C11:6.5 表达式:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. [...]

表达式

 baz.foo = 3.14 * baz.bar;  

具有明确定义的行为 如果 bar 之前初始化。原因是 baz.foo 的副作用是相对于对象 baz.foobaz.bar.

的值计算排序的

6.5.16 (p3):

[...] The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.

免责声明:此答案针对 C++。

您正在访问一个生命周期尚未开始的对象 - baz.bar - 这会导致 UB [basic.life]/(6.1)。

假设 bar 已经生效(例如通过初始化),您的代码没问题;在赋值之前,foo不需要存活,因为没有执行依赖于它的值的操作,并且期间,通过重用内存和有效初始化来更改活动成员它。目前的规则对后者并不清楚;参见 CWG #1116。然而现状是,这样的赋值确实是将目标成员设置为active(=alive)

请注意,赋值在操作数的值计算之后排序(即保证发生)- 参见 [expr.ass]/1。