Ceci est une excellente question. Cela m'a incité à voir s'il y avait un moyen de déterminer l'endianness à la compilation en utilisant l'expression constexpr.
Il s'avère que sans astuces de préprocesseur, cela n'est pas possible, car il est impossible de transformer un entier en une séquence d'octets (via des conversions ou des unions) lors de l'évaluation dans un contexte constexpr.
Cependant il se trouve que dans gcc, un simple contrôle d'exécution est optimisé de façon loin lorsqu'il est compilé avec -O2, donc c'est en fait d'une efficacité optimale:
#include <cstdint>
#include <iostream>
constexpr bool is_little_endian()
{
union endian_tester {
std::uint16_t n;
std::uint8_t p[4];
};
constexpr endian_tester sample = {0x0102};
return sample.p[0] == 0x2;
}
template<class Int>
Int to_little_endian(Int in)
{
if (is_little_endian()) {
return in;
}
else {
Int out = 0;
std::uint8_t* p = reinterpret_cast<std::uint8_t*>(std::addressof(out));
for (std::size_t byte = 0 ; byte < sizeof(in) ; ++byte)
{
auto part = (in >> (byte * 8)) & 0xff;
*p++ = std::uint8_t(part);
}
return out;
}
}
int main()
{
auto x = to_little_endian(10);
std::cout << x << std::endl;
}
est ici la sortie assembleur lors de la compilation sur une plate-forme Intel (little-endian):
main:
subq $8, %rsp
#
# here is the call to to_little_endian()
#
movl $10, %esi
#
# that was it - it's been completely optimised away
#
movl std::cout, %edi
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
movq %rax, %rdi
call std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
xorl %eax, %eax
addq $8, %rsp
ret
Qu'essayez-vous d'accomplir? À moins de faire un casting et un déréférencement funky de pointeurs vers des entiers de tailles différentes, vous n'avez pas besoin de vous soucier de l'endianess. Voir aussi cette question sur ["htonl() vs __builtin_bswap32()"] (http://stackoverflow.com/questions/21527957/htonl-vs-builtin-bswap32) qui parle d'autres façons d'échanger des nombres par octets. – Jens
Si vous devez jouer avec l'endianess, vous marchez déjà dans les domaines de "non portable". Donc, isolez ceci de telle sorte que le reste de votre code fonctionne avec des abstractions appropriées, et *** de petites implémentations spécifiques à la plate-forme sont implémentées pour des plates-formes spécifiques. –