Table of Contents
Endian Template (C++)
Work with big endian and little endian types in C++ without ever calling an "endian swap" function
Before downloading or using this product, make sure you understand and accept the terms of the license.
After downloading, make sure to follow the how to use instructions below; they're worth reading.
- Latest version: Endian Template(C++) version 2016-02-26 on GitHub
The Endian Template is a set of C++ template class and typedefs that allow you use little endian or big endian types, without having to write or concern yourself with "endian swap" functions, on any platform that supports at least the C++98 standard.
This provides a few benefits over other techniques:
- Guaranteed endian correctness when using a typedef
- No need to call "endian swap" functions
- No need for "endian detection macros", as everything is determined at compile-time / run-time
- Ability to wrap your own types with the provided templates
How to Use
- First, copy the header
tEndian.hinto your project.
- Next, include the header somewhere in your project or precompiled header if you use one.
You'll now have the following typedefs to use in your project:
leint64- Little endian signed types
leuint64- Little endian unsigned types
lefloat64- Little endian floating point types
beint64- Big endian signed types
beuint64- Big endian unsigned types
befloat64- Big endian floating point types
The naming conventions are based on those in C++ standard library header cstdint; the only addition being a prefix of
be to indicate little endian or big endian, respectively.
You'll also have the following template classes available for use in your project:
tLittleEndian<T>- Little endian template wrapper
tBigEndian<T>- Big endian template wrapper
With those template wrappers, you could in theory wrap your own types.
For instance, if you wanted to define a big endian version of
short, and a little endian version
long long, the following example code will achieve this:
typedef tBigEndian<size_t> besize; typedef tBigEndian<short> beshort; typedef tLittleEndian<long long> lelonglong;
You will also find a third template,
tEndianBase<T>, however it's only meant to be used as a helper class from the other template classes, so I don't suggest you use it directly yourself.
When using the endian types, you can literally just drop them in to replace your current types, as long as you also remove any endian swapping functions you're calling.
There are three primary reasons I see someone using the Endian Template:
- You're writing an emulator / virtual machine
- You're writing a binary file format reading / writing library
- Converting data sent over a network
I'll cover these three use cases, but forgive me as I'll be very brief with each.
Emulator / Virtual Machine
Of course, depending on the machine type, memory itself will be stored as big or little endian. However, it's typically when you're loading memory into registers, then doing math on those registers, when endianness starts to matter.
That said, you could define each register as the proper endian type for the platform you're emulating, and you won't have to worry or remember about shifting memory one way or another after a math operation– it just gets stored correctly on it's own.
Binary file formats
Binary formats are compact but are a potential minefield when dealing with different CPU architectures. The Endian Template can help here too.
I used to love writing things like image decoders for formats like BMP and the like. For example, in a BMP file, the first two bytes are typically
BM, but the next four bytes are "the size of the BMP file"– in little endian format.
If you read this data into an
uint32_t, you're fine as long as you're on a little endian machine (like an x86-based PC.) Not so much if you end up running your code on a PowerPC CPU, which is big endian.
So take the guesswork out of the equation– read it into an
leuint32 instead and it'll always work, regardless of the architecture.
Sending data over a network
If you're familiar with Network Byte Order, you'll know that the functions
ntohs are generally suggested to use before sending data over a network.
Since "Network Byte Order" is just "big endian"; instead you can now just define your data as
tBigEndian<unsigned short> and discard the conversion functions completely.
And regardless of the endian of computer's CPU, the code will always work.
Running the unit tests
The Endian Template comes with a unit test class,
tEndianTests.cc, and three project files:
/project/win/EndianTests.sln- Visual Studio 2005, Windows console target
/project/mac/EndianTests.xcodeproject- Xcode 7 Mac OS console target
/project/ios/EndianTests.xcodeproject- Xcode 7 iOS console target
When running the unit test on Visual Studio, note you will first need to convert the solution to the latest version. You'll also need to put a breakpoint on the last line of the
main function, as the console window containing the results of the test will close on exit.
When running the unit test on Mac or for iOS, the results of the test will be printed in Xcode's debug console, which is at the bottom right of Xcode's window.
Also, when running for iOS, you'll note that an app won't appear or launch in the simulator or on a device, as the tests are purely meant to display in the debug console.
(If you're curious, these project files were generated with Google GYP; the source project file is located in
Q & A
If you have a question not answered here, please feel free to contact me and ask.
- Q: What makes this better or different than Boost.Endian?
- A: I can't say for certain if it's better. The Endian Template is small, and only provides a minimum of what's needed to handle automatic endian conversion.
As I understand it Boost.Endian provides three different mechanisms for handling endian (one providing swapping functions), whereas my primary philosophy here is "don't use swapping functions."
Just for trivia: I originally created this class in 2001 as a proof-of-concept, hoping I could use it in some emulation projects (never got around to those unfortunately.) This predates when Boost.Endian came out, which was around 2002 or 2003.
That said, I've used boost (in general) before on a day-to-day basis for a client project. I'm not a boost "hater", but I'm not a regular user of it either.
February 26, 2016
- Renamed typedefs without
_tpostfix notation as this appears to be "reserved" by POSIX (thanks to reddit user "doodle77")
- Added required includes directly into
tEndian.h(thanks to reddit user "louiswins")
- Changed endian testing method to use reinterpret_cast, as the previous was using "type punning", which in theory can have undefined behavior (thanks to reddit user "NasenSpray")
- Removed ::PassThru method as a small optimization
February 23, 2016
- Added GitHub link to download section
- First public release
- Created project page