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(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I found https://s-macke.github.io/jor1k/demos/compile.html helpful to try a more promising approach.