what really means by type-punning in the union? for example
#include <iostream>
using namespace std;
union test {
int x;
float y;
};
int main()
{
test t;
t.y = 1.5;
cout<<t.x;
return 0;
}
gives output as 1069547520
what does this value represent? how to predict this?
Type-puning means reinterpreting the underlying bytes of one type as bytes of another. Unions can be (mis)used for this because all members share the same memory location.
Reading from non-active union member is undefined behaviour in C++. It is allowed in C and GNU C++.
The correct C++ approach for trivially copyable types is to use std::memcpy
:
#include <cstring>
int main()
{
std::uint32_t x = 12;
float y;
// This is OK, but the value of `y` is implementation-defined.
std::memcpy(&y,&x,sizeof(x));
// THIS IS UNDEFINED BEHAVIOUR.
y = *reinterpret_cast<float*>(&x);
static_assert(sizeof(x)==sizeof(y),"Sanity check");
}
Note that reinterpret_cast<T*>(address)
is not enough because it requires T
object to exist at address
otherwise you are breaking the strict aliasing rule (with some exceptions). There is also no need to worry about performance degradation of using std::memcpy
, with optimizations no bytes will be copied unless needed. The call will just serve as a hint to the compiler that you really meant to do that.
Although, the example above does not exhibit undefined behaviour, the value of y
still depends on precise bit representation of integers and floats which are mostly implementation-defined. In C++20 the integers are required to use 2-complement but floats are not required to adhere to e.g. IEEE 754.