Owen Jacobson wrote in
in comp.lang.c++:
Does the following invoke UB?
Yes, as soon as you read a union field that wasn't the last one
writen you get UB.
Further, will it reliably reverse the
bytes in the input argument on all conforming platforms?
Once you have UB, conforming (to the standard nolonger applies),
but perhaps you mean "how portable is this", it will probably
work on most platforms, the real problem is reading out.object
as reversing the bytes may put even simple types (say int) in
an invalid state.
template <typename T>
T ReverseByteOrder (T input) {
union {
T object;
unsigned char bytes[sizeof (T)];
} in, out;
in.object = input;
for (unsigned i = 0; i < sizeof (T); i++)
out.bytes[sizeof (T) - i - 1] = in.bytes;
return out.object;
}
This has the same *real* problems as your code, it avoids
the UB introduced by the union though, so in /theory/ it
may be slightly more portable.
#include <iostream>
#include <ostream>
#include <iomanip>
#include <algorithm>
template < typename T >
T reverse( T const &arg )
{
T nrv( arg );
// reinterpret_cast ..
unsigned char *p = (unsigned char *)&nrv;
// don't you just love namespaces ...
std::reverse( p, p + sizeof( nrv ) );
// Now for the UB ...
return nrv;
}
int main()
{
int i = 0x12345678;
int r = reverse( i );
std::cout << std::hex << r << std::endl;
}
The above also exhibits UB, but in this case its returning the
int value and its subsequent use, as it may now contain a trap
value.
Of course as long as we know that on our target platforms
an int can be reversed, then everthing is fine.
Rob.