Introduction
When exchanging data between different systems, such as in network communication or reading/writing binary files, the difference in Endianness (Byte Order) can be a problem. Endianness refers to the order in which data consisting of multiple bytes is arranged in memory, and there are mainly the following two types:
- Little Endian: Stores the lower bytes at smaller memory addresses. (Example: Intel x86 CPUs)
- Big Endian: Stores the upper bytes at smaller memory addresses. (Example: Network protocols)
In C++20, standard and highly portable tools were introduced to determine the endianness of the environment running the program and to convert (byte swap) the endianness. This article explains how to use std::endian and std::byteswap provided in the <bit> header.
Prerequisite: What is C++20?
C++20 is a major update to the C++ language formalized in 2020. Since the features introduced in this article were added in C++20, you need a compiler that supports C++20 to use them.
Sample Code for Determining and Converting Endianness
This code first determines whether the current execution environment is Little Endian or Big Endian. Then, it reverses the byte order of some numbers using the byteswap function and displays the results.
Complete Code
#include <iostream>
#include <bit> // std::endian, std::byteswap
#include <cstdint> // uint16_t, uint32_t, uint64_t
using namespace std;
int main() {
// 1. Determine the endianness of the current environment
if constexpr (endian::native == endian::little) {
cout << "Current environment: Little Endian" << endl;
} else if constexpr (endian::native == endian::big) {
cout << "Current environment: Big Endian" << endl;
} else {
cout << "Current environment: Other Endian" << endl;
}
cout << "\n--- Example of Byte Swap ---" << endl;
// 2. Convert byte order with byteswap
uint16_t val16 = 0xABCD; // 2-byte integer
uint32_t val32 = 0x1234ABCD; // 4-byte integer
cout << hex << showbase; // Hexadecimal display mode (with 0x prefix)
cout << val16 << " => " << byteswap(val16) << endl;
cout << val32 << " => " << byteswap(val32) << endl;
return 0;
}
Execution Result (In a Little Endian Environment)
Current environment: Little Endian
--- Example of Byte Swap ---
0xabcd => 0xcdab
0x1234abcd => 0xcdab3412
Code Explanation
1. Determining Endianness (std::endian)
if constexpr (endian::native == endian::little)
std::endian: An enumeration type defined in the<bit>header. It has three enumerators:little(Little Endian),big(Big Endian), andnative(implementation-dependent).endian::native: Represents the endianness of the environment where the compilation is taking place.if constexpr: Evaluates the conditional branch at compile time. This allows optimization of code dependent on the execution environment with zero runtime cost.
2. Converting Byte Order (std::byteswap)
byteswap(val16)
std::byteswap: A function provided in the<bit>header. It returns a value with the byte sequence of the integer passed as an argument completely reversed.- Example:
- 2-byte data
0xABCDis a sequence ofAB CDin memory.byteswapreverses this toCD AB, resulting in the value0xCDAB. - 4-byte data
0x1234ABCDis reversed from12 34 AB CDtoCD AB 34 12, resulting in0xCDAB3412.
- 2-byte data
Summary
In this article, I explained how to determine and convert endianness using std::endian and std::byteswap introduced in C++20.
std::endian::native: Allows determining the execution environment’s endianness at compile time.std::byteswap(value): Allows reversing the byte order of integers safely and efficiently.
By using these standard features, byte order-related processing, which previously required complex custom implementations, can now be written with highly portable and concise code.
