问题
I have referred many questions in SO on this topic, but couldn't find any solution so far. One natural solution was mentioned here: Determining endianness at compile time.
However, the related problems mentioned in the comments & the same answer.
With some modifications, I am able to compile a similar solution with g++ & clang++ (-std=c++11
) without any warning.
static_assert(sizeof(char) == 1, "sizeof(char) != 1");
union U1
{
int i;
char c[sizeof(int)];
};
union U2
{
char c[sizeof(int)];
int i;
};
constexpr U1 u1 = {1};
constexpr U2 u2 = {{1}};
constexpr bool IsLittleEndian ()
{
return u1.i == u2.c[0]; // ignore different type comparison
}
static_assert(IsLittleEndian(), "The machine is BIG endian");
Demo.
Can this be considered a deterministic method to decide the endian-ness or does it miss type-punning or something else?
回答1:
Since C++20 you can use std::endian from the <type_traits>
header:
#include <type_traits>
int main()
{
static_assert(std::endian::native==std::endian::big,
"Not a big endian platform!");
}
See it live
回答2:
Your attempt is no different from this obviously non-working one (where IsLittleEndian()
is identical to true
):
constexpr char c[sizeof(int)] = {1};
constexpr int i = {1};
constexpr bool IsLittleEndian ()
{
return i == c[0]; // ignore different type comparison
}
static_assert(IsLittleEndian(), "The machine is BIG endian");
I believe that C++11 doesn't provide means to programatically determine the endianness of the target platform during compile time. My argument is that the only valid way to perform that check during runtime is to examine an int
variable using an unsigned char
pointer (since other ways of type punning inevitably contain undefined behavior):
const uint32_t i = 0xffff0000;
bool isLittleEndian() {
return 0 == *reinterpret_cast<const unsigned char*>(&i);
}
C++11 doesn't allow to make this function constexpr
, therefore this check cannot be performed during compile time.
来源:https://stackoverflow.com/questions/39763611/finding-endian-ness-programmatically-at-compile-time-using-c11