M.M
M.M

Reputation: 141648

Assignment between union members

Is this code well-defined?

int main()    
{    
    union     
    {    
        int i;    
        float f;    
    } u;    

    u.f = 5.0;    
    u.i = u.f;       // ?????
}    

It accesses two different union members in one expression so I am wondering if it falls foul of the [class.union]/1 provisions about active member of a union.

The C++ Standard seems to underspecify which operations change the active member for builtin types, and what happens if an inactive member is read or written.

Upvotes: 15

Views: 714

Answers (3)

Daniel Jour
Daniel Jour

Reputation: 16156

The assignment operator (=) and the compound assignment operators all group right-to-left. [...] In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. [...]

[N4431 §5.18/1]

Under the premise that in your case the value computation of the left hand side (involving merely a member access, not a read) does not cause undefined behaviour, I'd apply the above as follows:

  1. The value computation of the right side reads u.f, which is the active member of the union. So everything is good.
  2. The assignment is executed. This involves writing the obtained result to u.i, which now changes the active member of the union.

Upvotes: 6

MSalters
MSalters

Reputation: 180145

Inactive members can be written to. That is in fact the only way to make them active. The active member has no restrictions; it can be read from and written to.

You can take the address of an inactive member. This is a valid way to perform the write:

union {
  int i;
  float f;
} u;
float* pf = &u.f; // Does NOT change the active member.
u.i = 3;
*pf = 3.0; // Changes the active member.

In your example, the active member can only become u.i by writing 5 to it, which means that the value u.f must have been read.

Upvotes: 4

marom
marom

Reputation: 5230

By looking at [class.union]/1, from the considerations about standard layout unions containing standard layout unions sharing a common initial sequence it means that the following is ok

int main()
{
   union 
   {
      union 
      {
          int x ;
          float y ;
      } v ;
      union 
      {
          int x ;
          double z ;
      } w ;      
   } u ;

   u.v.x = 2 ;
   int n = u.w.x ; // n contains 2
}

Here the common initial sequence is int x ;.

That's not the exactly the question but tells us that this kind of mix is OK.

Upvotes: -2

Related Questions