So I know how to detect endianness programmatically.
Question
Is there more standard or native (closed box) way of detecting endianness? does WINAPI offer such solution?
So I know how to detect endianness programmatically.
Is there more standard or native (closed box) way of detecting endianness? does WINAPI offer such solution?
There is no standard C++ provided functionality for detecting endian. Both myself, and Beman Dawes are working to correct that. However success in such an endeavor is both glacially slow and far from assured.
I have been experimenting with the following header:
https://github.com/HowardHinnant/hash_append/blob/master/endian.h
which as shown is not portable to Windows, but certainly could be easily ported to Windows by a std::lib implementor. The mechanism is very simplistic:
// endian provides answers to the following questions:
// 1. Is this system big or little endian?
// 2. Is the "desired endian" of some class or function the same as the
// native endian?
enum class endian
{
native = // unspecified,
little = // unspecified,
big = // unspecified
};
If you are on a little endian machine, then endian::native == endian::little
.
If you are on a big endian machine, then endian::native == endian::big
.
If you are on a mixed endian machine (I haven't seen one in a long while), then endian::native
has a value other than big
or little
.
This file:
https://github.com/HowardHinnant/hash_append/blob/master/hash_append.h
shows some example uses of this facility. For example there is something called a Hasher
that can request that scalars supplied to it come in one of three forms:
And there is a little utility that will reverse (or not) the bytes of the scalar, depending on the wishes of the Hasher
, and the native endian of the platform:
template <class T>
constexpr
inline
void
reverse_bytes(T& t)
{
unsigned char* bytes = static_cast<unsigned char*>(std::memmove(std::addressof(t), std::addressof(t), sizeof(T)));
for (unsigned i = 0; i < sizeof(T)/2; ++i)
std::swap(bytes[i], bytes[sizeof(T)-1-i]);
}
template <class T>
constexpr
inline
void
maybe_reverse_bytes(T& t, std::true_type)
{
}
template <class T>
constexpr
inline
void
maybe_reverse_bytes(T& t, std::false_type)
{
reverse_bytes(t);
}
template <class T, class Hasher>
constexpr
inline
void
maybe_reverse_bytes(T& t, Hasher&)
{
maybe_reverse_bytes(t, std::integral_constant<bool,
Hasher::endian == endian::native>{});
}