Portability Concerns for Network Byte Order Conversions of 64-Bit Integers in C
In C , the necessity arises to convert 64-bit integers to "network byte order" for specific applications, such as implementing the memcache protocol. Despite the existence of the htonl() function for converting 32-bit integers, a similar function for 64-bit integers (htonll()) remains elusive.
Standard Function Considerations
Unfortunately, there is currently no portable standard function in C that can perform 64-bit network byte order conversions. This absence creates the need for custom implementations.
Custom Implementation
To implement htonll(), we must first determine the system's endianness. One reliable method is to evaluate the value of an integer variable with known byte ordering (e.g., 42) at runtime:
<code class="cpp">static const int num = 42; bool isBigEndian = (*reinterpret_cast<const char *>(&num) == num);</code>
Next, we can perform the conversion according to the endianness:
<code class="cpp">uint64_t htonll(uint64_t value) { if (isBigEndian) { const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32)); const uint32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL)); return (static_cast<uint64_t>(low_part) << 32) | high_part; } else { return value; } }
Macros for Portability
Alternatively, macros can provide a concise way to define htonll() and its counterpart, ntohll():
<code class="cpp">#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))</code>
These macros rely on the system's intrinsic byte ordering behavior to determine the necessary byte-swapping.
Compiler-Specific Macros
Some compilers and operating systems provide specific macros for determining endianness. For example, on systems that support it, we can use:
<code class="cpp">#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</code>
By employing these techniques, custom implementations of htonll() and ntohll() can be made portable across various systems and compilers.
The above is the detailed content of How to Achieve Portability When Converting 64-Bit Integers to Network Byte Order in C ?. For more information, please follow other related articles on the PHP Chinese website!