在C++中是否有64位整数的"标准"类似htonl的函数?

ere*_*eOn 60 c++ 64-bit portability endianness htonl

我正在研究memcache协议的实现,在某些点上,它使用64位整数值.这些值必须以"网络字节顺序"存储.

我希望有一些uint64_t htonll(uint64_t value)功能可以进行更改,但不幸的是,如果它存在,我找不到它.

所以我有1或2个问题:

  • 是否有任何可移植(Windows,Linux,AIX)标准功能?
  • 如果没有这样的功能,你会如何实现它?

我想到了一个基本的实现,但我不知道如何在编译时检查字节序以使代码可移植.所以你的帮助非常受欢迎;)

谢谢.


这是我写的最终解决方案,感谢Brian的解决方案.

uint64_t htonll(uint64_t value)
{
    // The answer is 42
    static const int num = 42;

    // Check the endianness
    if (*reinterpret_cast<const char*>(&num) == num)
    {
        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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Bri*_*ndy 16

你可能正在寻找bswap_64我认为它几乎被支持,但我不会称之为标准.

您可以通过创建值为1的int,将int的地址转换为a char*并检查第一个字节的值来轻松检查字节序.

例如:

int num = 42;
if(*(char *)&num == 42)
{
   //Little Endian
}
else
{
   //Big Endian
} 
Run Code Online (Sandbox Code Playgroud)

知道了这一点,你也可以做一个简单的交换功能.


您也可以始终使用包含可移植跨平台的endian宏的boost.

  • 从技术上讲,只是字节交换并不总是足够的.有些系统是中端的(虽然没有*现代*系统).此外,`bswap_64`绝对是*不支持*; 单看系统的一长串`bswap_64`丢失:https://www.gnu.org/software/gnulib/manual/html_node/bswap_005f64.html (4认同)
  • 为了确保其他人知道,“bswap_64”始终假设需要交换,而“htobe64”,如“htonl”,如果网络字节顺序(大端)与计算机系统的字节顺序/端相匹配,则只会返回其参数。 (2认同)

del*_*106 15

#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))
Run Code Online (Sandbox Code Playgroud)

测试(1 == htonl(1))简单地确定(在运行时遗憾地)硬件架构是否需要字节交换.没有任何可移植的方法可以在编译时确定架构是什么,所以我们使用"htonl",这在这种情况下是可移植的.如果需要进行字节交换,那么我们使用htonl一次交换32位(记住也要交换两个32位字).


sur*_*h m 6

您可以尝试使用uint64_t htobe64(uint64_t host_64bits)uint64_t be64toh(uint64_t big_endian_64bits),反之亦然。

  • 好吧,不,我不能,因为自从接触该代码库已有6年了;) (2认同)

pix*_*x0r 5

这似乎适用于 C;我做错了什么吗?

uint64_t htonll(uint64_t value) {
    int num = 42;
    if (*(char *)&num == 42) {
        uint32_t high_part = htonl((uint32_t)(value >> 32));
        uint32_t low_part = htonl((uint32_t)(value & 0xFFFFFFFFLL));
        return (((uint64_t)low_part) << 32) | high_part;
    } else {
        return value;
    }
}
Run Code Online (Sandbox Code Playgroud)