N'utilisez pas de union
!
C ++ n'autorise pas la punition de type via union
s!
Lire à partir d'un champ union qui n'était pas le dernier champ écrit est un comportement indéfini !
De nombreux compilateurs prennent en charge cette fonctionnalité en tant qu'extensions, mais le langage n'offre aucune garantie.
Voir cette réponse pour plus de détails:
https://stackoverflow.com/a/11996970
Il n'y a que deux réponses valides qui sont garanties d'être portables.
La première réponse, si vous avez accès à un système qui prend en charge C ++ 20,
est d'utiliser à std::endian
partir de l'en- <type_traits>
tête.
(Au moment de la rédaction de ce document, C ++ 20 n'a pas encore été publié, mais à moins que quelque chose n'affecte std::endian
l'inclusion de, cela doit être le moyen préféré de tester l'endianité au moment de la compilation à partir de C ++ 20.)
À partir de C ++ 20
constexpr bool is_little_endian = (std::endian::native == std::endian::little);
Avant C ++ 20, la seule réponse valide consiste à stocker un entier, puis à inspecter son premier octet via la punition de type.
Contrairement à l'utilisation de union
s, cela est expressément autorisé par le système de type C ++.
Il est également important de se rappeler que pour une portabilité optimale static_cast
doit être utilisé,
car la reinterpret_cast
mise en œuvre est définie.
Si un programme tente d'accéder à la valeur stockée d'un objet via une valeur gl autre que l'un des types suivants, le comportement n'est pas défini: ... a char
ou unsigned char
type.
À partir de 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 et suivants (sans énumération)
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);
}