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?
uint8_t(u2.i)
produce the same value on either endianness? A cast should be value preserving, not just pick the first byte. – Weanlingun
]signed
]char
applies touint8_t
. – Louiselouisette1 == 1
and returntrue
. – Weanlingsizeof(char) == 1
is true by definition.sizeof
is given in units ofchar
, so this assertion can literally never fail. – Gynandrousconstexpr
to do this, since anyunion
/reinterpret_cast
approach invokes UB (which is caught at compile time inside aconstexpr
), andmemcpy
is notconstexpr
. Compiler specific macros are the only way around it (look for __BYTE_ORDER). – Johathanunion
will cause UB. It doesn't generate any warning in either g++/clang++. BTW, regarding compiler specific macros, there is a platform specific file supported,<endian.h>
, as mentioned in this answer: C Macro definition to determine big endian or little endian machine? – Pluralize__ORDER_LITTLE_ENDIAN__
(& big, native)' not enough? IMO, enum trick is trivial and hence not needed. – Pluralizeconst char* const ENDIANESS = "little";
orconst char* const ENDIANESS = "big";
into a file "endianess.h", which is then used by your actual source code. – Tidemark0x01020304
being stored as0x03 0x04 0x01 0x02
. So, if I were you, I would write the test withchar[8] = {1, 2, 3, 4, 5, 6, 7, 8};
, copy over to at least auint64_t
, and then check for equality with either0x0102030405060708
or0x0807060504030201
. If neither test succeeds, you should probably error out hard. – Tidemark