Search code examples
c++undefined-behaviorunionsmemcpy

Using memcpy to switch active member of union in C++


I know about the memcpy/memmove to a union member, does this set the 'active' member? question , but I guess my question is different. So:

Suppose sizeof( int ) == sizeof( float ) and I have the following code snippet:

union U{
    int i;
    float f;
};

U u;
u.i = 1; //i is the active member of u

::std::memcpy( &u.f, &u.i, sizeof( u ) ); //copy memory content of u.i to u.f

My questions:

  1. Does the code lead to an undefined behaviour (UB)? If yes why?
  2. If the code does not lead to an UB, what is the active member of u after the memcpy call and why?
  3. What would be the answer to previous two questions if sizeof( int ) != sizeof( float ) and why?

Solution

  • Regardless of the union, the behaviour of std::memcpy is undefined if the source and destination overlap. This is the case for every member of the union, and it would not be different if the sizes weren't the same.

    If you were to use std::memmove instead, there is no longer an issue due to the overlap, and it also doesn't matter that you copy from a member of a union. Since both types are trivially copyable, the behaviour is defined and u.f becomes the active member of the union, but the union holds the same bytes as before in practice.

    The only issue would arise if sizeof(U) was larger than sizeof(int), because you would be copying potentially uninitialized bytes. This is undefined behaviour.