C++ 有没有“什么”呢;标准;C+;中64位整数的类htonl函数+;?

C++ 有没有“什么”呢;标准;C+;中64位整数的类htonl函数+;?,c++,64-bit,portability,endianness,htonl,C++,64 Bit,Portability,Endianness,Htonl,我正在研究memcache协议的一个实现,它在某些情况下使用64位整数值。这些值必须以“网络字节顺序”存储 我希望有一些uint64\u t htonll(uint64\u t value)函数来进行更改,但不幸的是,如果它存在,我找不到它 所以我有一两个问题: 是否有可移植的(Windows、Linux、AIX)标准函数来执行此操作 如果没有这样的功能,您将如何实现它 我想到了一个基本的实现,但我不知道如何在编译时检查endianness以使代码可移植。所以这里非常欢迎您的帮助;) 多谢各

我正在研究memcache协议的一个实现,它在某些情况下使用64位整数值。这些值必须以“网络字节顺序”存储

我希望有一些
uint64\u t htonll(uint64\u t value)
函数来进行更改,但不幸的是,如果它存在,我找不到它

所以我有一两个问题:

  • 是否有可移植的(Windows、Linux、AIX)标准函数来执行此操作
  • 如果没有这样的功能,您将如何实现它
我想到了一个基本的实现,但我不知道如何在编译时检查endianness以使代码可移植。所以这里非常欢迎您的帮助;)

多谢各位


这是我写的最终解决方案,感谢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;
    }
}
uint64\u t htonll(uint64\u t值)
{
//答案是42
静态常数int num=42;
//检查端部
如果(*重新解释类型(&num)==num)
{
const uint32_t high_part=htonl(静态强制转换(值>>32));
const uint32_t low_part=htonl(静态强制转换(值&0xFFFFFFFFL));

return(static_cast(low_part)您可能正在寻找
bswap_64
我认为它几乎在任何地方都受支持,但我不认为它是标准的

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

例如:

int num = 42;
if(*(char *)&num == 42)
{
   //Little Endian
}
else
{
   //Big Endian
} 
知道了这一点,您还可以制作一个简单的函数来进行交换


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

编辑:将两者结合(使用Brian的代码):

uint64\u t htonll(uint64\u t值)
{
int num=42;
如果(*(字符*)&num==42)
返回(htonl(值&0xFFFFFFFF)>32);
其他的
返回值;
}

警告:未测试的代码!请在使用前进行测试。

这在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;
    }
}
uint64\u t htonll(uint64\u t值){
int num=42;
如果(*(字符*)&num==42){
uint32_t高_部分=htonl((uint32_t)(值>>32));
uint32_t low_part=htonl((uint32_t)(值&0xffffffl));

返回((uint64_t)low_部分)以减少“if num==…”的开销 使用预处理器定义:

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#else
#endif
定义htonl(x)((1==htonl(1))?(x):((uint64)htonl((x)和0xFFFFFFFF)>32)) #定义ntohl(x)((1==ntohl(1))?(x):((uint64_t)ntohl((x)&0xFFFFFFFF)>32))
测试(1==htonl(1))只是确定(在运行时)硬件架构是否需要字节交换。没有任何可移植的方法在编译时确定架构是什么,所以我们求助于使用“htonl”如果需要字节交换,那么我们使用htonl一次交换32位(记住也交换两个32位字)


下面是另一种执行交换的方法,它可以在大多数编译器和操作系统(包括AIX、BSDs、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
\if\u BIG\u ENDIAN__
#定义htonll(x)(x)
#定义Ntohl(x)(x)
#否则
#定义htonl(x)((uint64_t)htonl((x)和0xFFFFFFFF)>32))
#定义ntohl(x)((uint64_t)ntohl((x)和0xFFFFFFFF)>32))
#恩迪夫

重要的部分是使用
\u BIG\u ENDIAN\u
\u LITTLE\u ENDIAN\u
;而不是
\u BYTE\u ORDER\u
\u ORDER\u BIG\u ENDIAN\u
\u ORDER\u LITTLE\u ENDIAN\u
。一些编译器和操作系统缺少
\u BYTE\u顺序
\u和朋友。
(uint64主机64位)&
uint64字节(uint64字节)
反之亦然。

好吧,我认为在编译时尽量使用endian切换更好,但我更喜欢使用函数而不是宏,因为在宏中参数只是被参数替换;因此参数可以多次求值,如果参数在宏(如前面提供的一些解决方案所述)

uint64\u t htonll(uint64\u t x)
{
#如果(大)(大)__
返回x;
#否则
返回((uint64_t)htonl((x)和0xFFFFFFFFLL)>32);
#恩迪夫
}
uint64_t ntohll(uint64_t x)
{
#如果(大)(大)__
返回x;
#否则
返回((uint64_t)ntohl((x)和0xfffffffl)>32);
#恩迪夫
}

因此,这允许调用htonll(x++)而不增加x几次,就像使用以前的宏一样。

谢谢;)boost宏看起来很有趣。你有链接吗?从技术上讲,仅仅交换字节并不总是足够的。有些系统是中端的(尽管没有现代系统是这样的)。此外,
bswap_64
肯定不是到处都支持的;只要看看一长串缺少
bswap_64
的系统:请注意,
bswap_64
不是。
bswap_64
在Solaris i86pc上不存在。有人知道它是否存在于AIX上吗?可能与此重复@ereOn:我也有类似的问题。如果可能的话,你能看一看,让我知道我在这里做错了什么吗?不要把你的答案包含在问题中,你应该让你的答案和答案一起出现。这样更可读。@Pavel仍然不起作用。
htonl()
返回一个不能调用的32位值
我认为通过32LL移位可以提升左侧,否?@Pavel:否,移位值的位大小不会改变任何内容。gcc发出警告:“左移位计数>=类型宽度”。并且您的函数表示htonll(0x0102030405060708ULL)==0xc070605。将其更改为
return((uint64_t)htonl(value&0xFFFFFFFF)>32);
并且它工作正常。我相信这个答案很好,但是您能添加一些代码以外的内容来解释什么和为什么吗?谢谢!我已经用
#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))
#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
uint64_t htonll(uint64_t x)
{
#if __BIG_ENDIAN__
    return x;
#else
    return ((uint64_t)htonl((x) & 0xFFFFFFFFLL) << 32) | htonl((x) >> 32);
#endif
}

uint64_t ntohll(uint64_t x)
{
#if __BIG_ENDIAN__
    return x;
#else
    return ((uint64_t)ntohl((x) & 0xFFFFFFFFLL) << 32) | ntohl((x) >> 32);
#endif
}