Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C/C++ unions and undefined behaviour

Is the following undefined behaviour?

 union {
   int foo;
   float bar;
 } baz;

 baz.foo = 3.14 * baz.bar;

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

like image 446
Vroomfondel Avatar asked Mar 14 '23 09:03

Vroomfondel


2 Answers

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

Reading and writing to the same memory location in the same expression does not invoke undefined behavior until and unless that location is modified more than once between two sequence points or the side effect is unsequenced relative to the value computation using the value at the same location.

C11: 6.5 Expressions:

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. [...]

The expression

 baz.foo = 3.14 * baz.bar;  

has well defined behaviour if bar is initialized before. The reason is that the side effect to baz.foo is sequenced relative to the value computations of the objects baz.foo and baz.bar.

C11: 6.5.16/3 Assignment operators:

[...] 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.

like image 82
haccks Avatar answered Mar 31 '23 16:03

haccks


Disclaimer: This answer addresses C++.

You're accessing an object whose lifetime hasn't begun yet - baz.bar - which induces UB by [basic.life]/(6.1).

Assuming bar has been brought to life (e.g. by initializing it), your code is fine; before the assignment, foo need not be alive as no operation is performed that depends on its value, and during it, the active member is changed by reusing the memory and effectively initializing it. The current rules aren't clear about the latter; see CWG #1116. However, the status quo is that such assignments are indeed setting the target member as active (=alive).

Note that the assignment is sequenced (i.e. guaranteed to happen) after the value computation of the operands - see [expr.ass]/1.

like image 32
Columbo Avatar answered Mar 31 '23 14:03

Columbo