How do I convert between big-endian and little-endian values in C++?
EDIT: For clarity, I have to translate binary data (double-precision floating point values and 3
If you take the common pattern for reversing the order of bits in a word, and cull the part that reverses bits within each byte, then you're left with something which only reverses the bytes within a word. For 64-bits:
x = ((x & 0x00000000ffffffff) << 32) ^ ((x >> 32) & 0x00000000ffffffff);
x = ((x & 0x0000ffff0000ffff) << 16) ^ ((x >> 16) & 0x0000ffff0000ffff);
x = ((x & 0x00ff00ff00ff00ff) << 8) ^ ((x >> 8) & 0x00ff00ff00ff00ff);
The compiler should clean out the superfluous bit-masking operations (I left them in to highlight the pattern), but if it doesn't you can rewrite the first line this way:
x = ( x << 32) ^ (x >> 32);
That should normally simplify down to a single rotate instruction on most architectures (ignoring that the whole operation is probably one instruction).
On a RISC processor the large, complicated constants may cause the compiler difficulties. You can trivially calculate each of the constants from the previous one, though. Like so:
uint64_t k = 0x00000000ffffffff; /* compiler should know a trick for this */
x = ((x & k) << 32) ^ ((x >> 32) & k);
k ^= k << 16;
x = ((x & k) << 16) ^ ((x >> 16) & k);
k ^= k << 8;
x = ((x & k) << 8) ^ ((x >> 8) & k);
If you like, you can write that as a loop. It won't be efficient, but just for fun:
int i = sizeof(x) * CHAR_BIT / 2;
uintmax_t k = (1 << i) - 1;
while (i >= 8)
{
x = ((x & k) << i) ^ ((x >> i) & k);
i >>= 1;
k ^= k << i;
}
And for completeness, here's the simplified 32-bit version of the first form:
x = ( x << 16) ^ (x >> 16);
x = ((x & 0x00ff00ff) << 8) ^ ((x >> 8) & 0x00ff00ff);