> Is there any real different between using an union between two types and a reinterpret_cast between two types
yes, there are quite a lot of differences.
a union reinterprets the layout of memory (depending on which member is accessed).
a reinterpret_cast is a conversion operator.
the conversions that can be performed using a reinterpret_cast are limited; the permissible ones are specified by the standard.
IS 5.2.10 - Reinterpret cast
-1- The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T.
...
Conversions that can be performed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.
-2- The reinterpret_cast operator shall not cast away constness. ...
-3- The mapping performed by reinterpret_cast is implementation-defined. ...
and then it goes on to list the conversions that can be performed explicitly using reinterpret_cast. for example this is what is specified about pointer to integral and integral to pointer conversions:
-4- A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined.
[Note: it is intended to be unsurprising to those who know the addressing structure of the underlying machine. ]
-5- A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined. [Footnote: Converting an integral constant expression with value zero always yields a null pointer, but converting other expressions that happen to have value zero need not yield a null pointer. --- end foonote]
and this is what is specified about a reinterpret_cast of one pointer type to a pointer of a different type:
-7- A pointer to an object can be explicitly converted to a pointer to an object of different type.
[Footnote: The types may have different cv-qualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness. --- end foonote]
Except that converting an rvalue of type ``pointer to T1'' to the type ``pointer to T2'' (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
however, for pointers to POD types, both a union and a reinterpret_cast should give identical results:
IS 5.4/5 says "...barring const_cast, C-style cast is equivalent to reinterpret_cast, (unless static_cast is possible)"
IS 9.5/1 "The size of a union is sufficient to contain the largest of its data members. Each data member is allocated as if it were the sole member of a struct"
IS 9.2/17 "A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member [...] and vice versa."
taken together, this seems pretty clear - these constrain the implementation of pointer reinterpret_cast; the source and destination pointer shall point to the same object (have the same value), unless this is impossible due to alignment requirements. even if they have different values (due to alignment requirements), the union and reinterpret_cast would give identical results.
an example showing some of the differences between union and reinterpret_cast:
#include <iostream>
int main()
{
union
{
short s ;
int i ;
double d ;
char bytes[ sizeof(double) > sizeof(int) ? sizeof(double)
: sizeof(int) ] ;
} ;
i = 123456789 ; // sets first sizeof(int) bytes of the union
// ok, interpret the first sizeof(int) bytes as an int
std::cout << "i: " << i << '\n'
// ok, interpret the first sizeof(double) bytes as a double
<< "d: " << d << '\n'
// ok, interpret the first sizeof(short) bytes as a short
<< "s: " << s << '\n'
// ok, interpret the third byte as a char
<< "bytes[3]: " << bytes[3] << '\n' ;
// ok, reinterpret reference to int as reference to double
std::cout << reinterpret_cast<double&>(i) << '\n' ;
// ok, reinterpret reference to int as reference to short
std::cout << reinterpret_cast<short&>(i) << '\n' ;
// ok, reinterpret pointer to int as pointer to double
std::cout << *reinterpret_cast<double*>(&i) << '\n' ;
// ok, reinterpret pointer to int as pointer to short
std::cout << *reinterpret_cast<short*>(&i) << '\n' ;
// ok, pd gets the (numeric) value of the int
double* pd = reinterpret_cast<double*>(i) ;
// ok, pd gets the (numeric) value of the short
pd = reinterpret_cast<double*>(s) ;
// error, no such reinterpret_cast is possible fom int to double
// std::cout << reinterpret_cast<double>(i) << '\n' ;
// error, no such reinterpret_cast is possible
// std::cout << reinterpret_cast<double>(s) << '\n' ;
}