Endianness in C++20
Endianness Basics
The endianness of a system refers to the order in which bytes are stored in memory or transmitted over a network. Big-Endian systems store the Most Significant Byte (MSB) at the lowest memory address. This is used in various network protocols to send data over a network, also known as Network Byte Order. In Little-Endian systems, the Least Significant Byte (LSB) is stored at the lowest memory address. For example, the hexadecimal number 0x12345678
would be stored as follows:
- Big-Endian:
Address | Value
---------------
n | 0x12
n + 1 | 0x34
n + 2 | 0x56
n + 3 | 0x78
- Little-Endian:
Address | Value
---------------
n | 0x78
n + 1 | 0x56
n + 2 | 0x34
n + 3 | 0x12
Depending on the architecture, your system may have a Host Byte Order of Big-Endian or Little-Endian. In x86 and x86–64 systems, Little-Endian is used. In ARM, both are supported but most devices will use Little-Endian. Some older architectures use Big-Endian.
Importance of Endianness
So, why is this important? If you need to send data over a network, then you need to ensure that it is transmitted in Network Byte Order. In most cases, your Host Byte Order will be Little-Endian, which means you would need to reverse the order of bytes before transmitting data. But what happens if you run the same code on a Big-Endian machine, which is already in Network Byte Order?
Checking Endianness
To ensure your code is portable across multiple processor architectures, your code should check the endianness of your machine. Prior to C++20, you would have to either use some compiler-specific macros like __BYTE_ORDER__
in GCC, or you could manually check by inspecting the individual bytes of a hexadecimal value converted to a byte array:
void checkEndianness() {
uint32_t value= 0x1234;
uint8_t* bytes = reinterpret_cast<uint8_t*>(&value);
if (bytes[0] == 0x34 && bytes[1] == 0x12) {
std::cout << "Little-endian" << std::endl;
} else if (bytes[0] == 0x12 && bytes[1] == 0x34) {
std::cout << "Big-endian" << std::endl;
} else {
std::cout << "Unknown" << std::endl;
}
}
However, C++20 introduced a much simpler and more portable way to check endianness with std::endian
. Now, you can check your system’s Host Byte Order with std::endian::native
. Below is a simple example:
void checkEndianness() {
if constexpr (std::endian::native == std::endian::little) {
std::cout << "Little-endian" << std::endl;
} else if constexpr (std::endian::native == std::endian::big) {
std::cout << "Big-endian" << std::endl;
} else {
std::cout << "Unknown" << std::endl;
}
}
Notice that constexpr
is used in order to evaluate the endianness at compile-time.