Last active
July 7, 2024 10:34
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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(); | |
} |
This won't work because it will always return LITTLE_ENDIAN on all platforms! Read:
The integer value 1 on big-endian platforms still behaves like the integer value 1, and will not magically become 0x01000000
This won't work, and this will always return LITTLE_ENDIAN.
The author misunderstands the memory representation of integers.
I found https://s-macke.github.io/jor1k/demos/compile.html helpful to try a more promising approach.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This should not work. b/c 1 is 0x00000001, no matter which endian cpu arch. So, your code will always return LITTLE_ENDIAN