Is there any "standard" htonl-like function for 64 bits integers in C++?
#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))
The test (1==htonl(1)) simply determines (at runtime sadly) if the hardware architecture requires byte swapping. There aren't any portable ways to determine at compile-time what the architecture is, so we resort to using "htonl", which is as portable as it gets in this situation. If byte-swapping is required, then we swap 32 bits at a time using htonl (remembering to swap the two 32 bit words as well).
Here's another way to perform the swap that is portable across most compilers and operating systems, including AIX, BSDs, Linux, and 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
The important part is to use __BIG_ENDIAN__
or __LITTLE_ENDIAN__
; and not __BYTE_ORDER__
, __ORDER_BIG_ENDIAN__
or __ORDER_LITTLE_ENDIAN__
. Some compilers and operating systems lack __BYTE_ORDER__
and friends.
You are probably looking for bswap_64
I think it is supported pretty much everywhere but I wouldn't call it standard.
You can easily check the endianness by creating an int with a value of 1, casting your int's address as a char*
and checking the value of the first byte.
For example:
int num = 42;
if(*(char *)&num == 42)
{
//Little Endian
}
else
{
//Big Endian
}
Knowing this you could also make a simple function that does the swapping.
You could also always use boost which contains endian macros which are portable cross platform.