Skip to content

Instantly share code, notes, and snippets.

@hamsham
Last active March 1, 2021 00:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hamsham/9849411 to your computer and use it in GitHub Desktop.
Save hamsham/9849411 to your computer and use it in GitHub Desktop.
A simple compile-time endianness checking system for programs written in C++11.
/*
* A simple compile-time endian test
* g++ -std=c++11 -Wall -Werror -Wextra -pedantic -pedantic-errors endian.cpp -o endian
*
* This can be used with specialized template functions, classes, and class
* methods in order better tailor code and reduce reliance on runtime
* checking systems.
*/
#include <cstdint>
#include <iostream>
/**
* endian_t
*
* This enumeration can be placed into templated objects in order to generate
* compile-time code based on a program's target endianness.
*
* The values placed in this enum are used just in case the need arises in
* order to manually compare them against the number order in the
* endianValues[] array.
*/
enum endian_t : uint32_t {
LITTLE_ENDIAN = 0x00000001,
BIG_ENDIAN = 0x01000000,
PDP_ENDIAN = 0x00010000,
UNKNOWN_ENDIAN = 0xFFFFFFFF
};
/**
* A simple function that can be used to help determine a program's endianness
* at compile-time.
*/
constexpr endian_t getEndianOrder() {
return
((0xFFFFFFFF & 1) == LITTLE_ENDIAN)
? LITTLE_ENDIAN
: ((0xFFFFFFFF & 1) == BIG_ENDIAN)
? BIG_ENDIAN
: ((0xFFFFFFFF & 1) == PDP_ENDIAN)
? PDP_ENDIAN
: UNKNOWN_ENDIAN;
}
/**
* Macro that should be used to always get the endianness of the current build
* target.
*/
#define _ENDIANNESS_ getEndianOrder()
///////////////////////////////////////////////////////////////////////////////
// Test Functions
///////////////////////////////////////////////////////////////////////////////
template <endian_t et>
void printEndianness() {
static_assert(et != UNKNOWN_ENDIAN, "Unknown Endianness");
}
template <>
void printEndianness<LITTLE_ENDIAN>() {
std::cout << "This machine is LITTLE endian" << std::endl;
}
template <>
void printEndianness<BIG_ENDIAN>() {
std::cout << "This machine is BIG endian" << std::endl;
}
template <>
void printEndianness<PDP_ENDIAN>() {
std::cout << "This machine is PDP endian" << std::endl;
}
#define printCurrentEndianness printEndianness<_ENDIANNESS_>
///////////////////////////////////////////////////////////////////////////////
// Main
///////////////////////////////////////////////////////////////////////////////
int main() {
#if defined _WIN32 || defined _WIN64
static_assert(
_ENDIANNESS_ == LITTLE_ENDIAN,
"Aren't Windows programs Little-Endian?"
);
#else
#error "I actually still need to test this on a non-little-endian CPU"
#endif
printCurrentEndianness();
}
@vladimirgamalyan
Copy link

I think it doesnt actualy work, because (0xFFFFFFFF & 1) always equals 0x00000001 on all platforms.

@boost2017
Copy link

This should not work. b/c 1 is 0x00000001, no matter which endian cpu arch. So, your code will always return LITTLE_ENDIAN

@vietlq
Copy link

vietlq commented Jun 14, 2018

@adrian-constantin
Copy link

The integer value 1 on big-endian platforms still behaves like the integer value 1, and will not magically become 0x01000000

@gavinchou
Copy link

This won't work, and this will always return LITTLE_ENDIAN.
The author misunderstands the memory representation of integers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment