Endianness
Category | System |
---|
Overview
Endianness is the sequential order in which bytes are arranged when stored in memory.
Bytes are represented in big-endian or little-endian format.
Bit Endianness
Bit endianness is the convention used to identify the bit positions in a binary number.
Least Significant Byte
The least significant byte (LSB) is the byte containing the least significant bit.
Most Significant Byte
The most significant byte (MSB) is the byte containing the most significant bit.
Byte Endianness
Big-endian
Bytes are ordered from the most significant bit to the least significant bit.
The most significant bit is stored first and the least significant bit is stored last.
Little-endian
Bytes are ordered from the least significant bit to the most significant bit.
The least significant bit is stored first and the most significant bit is stored last.
Bi-endianness
Some architectures feature a setting which allows for switchable endianness.
Hardware
Name | Endianness |
---|---|
ARM | bi-endian |
Intel x86 | little-endian |
Intel x86-64 | little-endian |
iOS | little-endian |
PlayStation 3 | big-endian |
PlayStation 4 | little-endian |
PlayStation 5 | little-endian |
Switch | little-endian |
Wii | big-endian |
Wii U | big-endian |
Xbox 360 | big-endian |
Xbox One | little-endian |
Xbox Scarlett | little-endian |
Byte Swap
When a binary file created on a platform is read on another platform with a different endianness, byte swapping is required.
Byte swap depends on the size of the numbers (ie. a 16-bit value and a 32-bit value require a different byte swap).
The data format must therefore be known to perform endianness conversion.
Implementations
16-bit integer: swap 2 bytes.
uint16_t Swap(uint16_t value)
{
uint16_t result = 0;
result |= (value & 0x00FF) << 8;
result |= (value & 0xFF00) >> 8;
return result;
}
32-bit integer: swap 4 bytes.
uint32_t Swap(uint32_t value)
{
uint32_t result = 0;
result |= (value & 0x000000FF) << 24;
result |= (value & 0x0000FF00) << 8;
result |= (value & 0x00FF0000) >> 8;
result |= (value & 0xFF000000) >> 24;
return result;
}
32-bit floating point:
- Perform a
reinterpret_cast
from the floating point value to a 32-bit integer. Swap the integer value and performed anotherreinterpret_cast
to cast the result back to a floating point value.
float Swap(float value)
{
uint32_t result = Swap(reinterpret_cast<uint32_t>(value));
return reinterpret_cast<float>(result);
}
- Store the floating point value to a temporary union of a float and 32-bit integer and swap the integer value.
float Swap(float value)
{
union
{
float f;
uint32_t u;
} swap;
swap.f = x;
swap.u = Swap(swapper.u);
return swap.f;
}
Strategies
There are two strategies when generating binary data.
- Byte swap when building the data for each target platform in the expected endianness.
- Byte swap when loading the data if the endianness of the data is different from the endianness of current platform.
References
- Endianness, Wikipedia, https://en.wikipedia.org/wiki/Endianness
- Bit numbering, Wikiepdia, https://en.wikipedia.org/wiki/Bit_numbering