#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
Тест (1 == htonl (1)) просто определяет (к сожалению, во время выполнения), требует ли аппаратная архитектура замены байтов.Во время компиляции не существует каких-либо переносимых способов определения архитектуры, поэтому мы прибегаем к использованию «htonl», который является настолько переносимым, насколько это возможно в этой ситуации.Если требуется замена байтов, то мы заменяем 32 бита за раз, используя htonl (не забывая также поменять местами два 32-битных слова).
Вот еще один способ выполнить своп, который переносим черезбольшинство компиляторов и операционных систем, включая AIX, BSD, Linux и Solaris.
#if __BIG_ENDIAN__
# define htonll(x) (x)
# define ntohll(x) (x)
#else
# define htonll(x) ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
# define ntohll(x) ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
#endif
Важной частью является использование __BIG_ENDIAN__
или __LITTLE_ENDIAN__
;а не __BYTE_ORDER__
, __ORDER_BIG_ENDIAN__
или __ORDER_LITTLE_ENDIAN__
.Некоторым компиляторам и операционным системам не хватает __BYTE_ORDER__
и друзей.