Не используйте union
!
C ++ не разрешает пробивание типов через union
s!
Чтение из поля объединения, которое не было последним записанным полем, является неопределенным поведением !
Многие компиляторы поддерживают это как расширения, но язык не дает никаких гарантий.
Смотрите этот ответ для более подробной информации:
https://stackoverflow.com/a/11996970
Есть только два правильных ответа, которые гарантированно будут переносимыми.
Первый ответ, если у вас есть доступ к системе, которая поддерживает C ++ 20,
это использовать std::endian
из <type_traits>
заголовка.
(На момент написания C ++ 20 еще не был выпущен, но если что-то не влияет на std::endian
на включение, это должно быть предпочтительным способом проверки порядка байтов во время компиляции начиная с C ++ 20 и далее.)
C ++ 20 г.в.
constexpr bool is_little_endian = (std::endian::native == std::endian::little);
До C ++ 20 единственный верный ответ - хранить целое число, а затем проверять его первый байт через тип punning.
В отличие от использования union
s, это явно разрешено системой типов C ++.
Также важно помнить, что для оптимальной переносимости static_cast
следует использовать,
потому что reinterpret_cast
реализация определена.
Если программа пытается получить доступ к сохраненному значению объекта через glvalue, отличный от одного из следующих типов, поведение не определено: ... a char
или unsigned char
тип.
C ++ 11 и далее
enum class endianness
{
little = 0,
big = 1,
};
inline endianness get_system_endianness()
{
const int value { 0x01 };
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01) ? endianness::little : endianness::big;
}
C ++ 11 и далее (без перечисления)
inline bool is_system_little_endian()
{
const int value { 0x01 };
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01);
}
C ++ 98 / C ++ 03
inline bool is_system_little_endian()
{
const int value = 0x01;
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01);
}