I Need to switch the order of bytes so that an int16 with contents (byte1, byte2) -> (byte2, byte1). I did this using a union:
union ConversionUnion
{
uint8_t m_8[4];
uint16_t m_16[2];
uint32_t m_32;
};
//use
uint16_t example = 0xFFDE
ConversionUnion converter;
converter.m_16[0] = example;
std::swap(converter.m_8[0], converter.m_8[1]);
example = converter.m_16[0]; //0xDEFF
Now this does work on gcc, but i have been informed that this is undefined behavior (gcc 6.3, C++11).
Questions:
1) Is this really undefined behavior, I ask because i've seen this before in embedded code. Other stackoverflow questions seem to debate this, who's actually correct (for C++11 & C++14).
2) If this is undefined behavior, can byte order swapping be done without a bunch of bit shifting in a portable way. I really hate bit shifting, its horribly ugly.
Type punning is allowed via char*, so why not just use that rather than a union?
uint16_t example = 0xFFDE;
char *char_alias = reinterpret_cast<char*>(&example);
std::swap(char_alias[0], char_alias[1]);
Relying on undefined behavior or obscure semantics of the language (union) is not necessarily more idiomatic or easier to read. I find this loop much easier to parse:
uint32_t example = 0xc001c0de;
unsigned char *p = reinterpret_cast<unsigned char*>(&example);
for (size_t low = 0, high = sizeof(example) - 1;
high > low;
++low, --high)
{
std::swap(p[low], p[high]);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With