Switching byte order without function
I need to switch the byte order to int16 with content (byte1, byte2) -> (byte2, byte1). I did it with a join:
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
This now works on gcc, but I was informed that this behavior is undefined (gcc 6.3, C ++ 11).
Questions:
1) This is indeed undefined behavior, I ask because I have seen this before in inline code. Other questions from stackoverflow seem to be discussing this, who is actually fixing it (for C ++ 11 and C ++ 14).
2) If this behavior is undefined, it is possible to perform byte byte swapping without confusing bit carry in a portable way. I really hate bit bias, its terribly ugly.
source to share
Relying on undefined behavior or obscure language semantics (union) is not necessarily more idiomatic or easier to read. I find this loop is 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]);
}
source to share
-
People disagree to some extent about this. I think that
it undefined behavior
but my opinion is not a valuable addition.
-
Swapping bytes is simple with unsigned types (signed BTW bytes don't make sense). Just extract the individual bytes and rearrange them. Hide the ugliness in a function
constexpr
or macro.constexpr uint16_t bswap(uint16_t value); { uint16_t high_byte = (value >> 8) & 0xff; uint16_t low_byte = value & 0xff; return (low_byte << 8) | high_byte; }
By the way, if you see something in the inline code and it works, it is not an indicator that it is safe! Inline code often sacrifices portability for efficiency, sometimes using undefined behavior where it was the only way to convince a particular compiler to generate efficient code.
source to share