负数的字节序转换?

时间:2020-06-15 14:53:23

标签: c++ linux endianness

当前,我正在一个网络项目中,在将这个长数据(64位)转换为big endian之后再通过套接字发送。为此,我正在使用htobe64(x)函数。在接收方客户端上,我正在使用be64toh(x)函数从big endian转换为主机字节顺序。对于像(132)这样的正数,这很好用,但是当数字为负数(-132)时,上述函数将返回一些晦涩的数字。我很困惑为什么即使在使用上述标准函数时也会发生这种情况。 目前正在ubuntu(linux)计算机上针对客户端和服务器进行测试。

例如,请参见下面的代码。

long a = -132;

cout << "=========" << endl;
cout << "a = " << a << endl;
cout << "htobe64 = " << htobe64(a) << endl;
long b = htobe64(a);
cout << "be64toh = " << be64toh(b) << endl;
cout << "=========" << endl;

输出为:

=========
a = -132
htobe64 = 9007199254740991999
be64toh = 18446744073709551484
=========

这对于正数工作正常。

=========
a = 132
htobe64 = 9511602413006487552
be64toh = 132
=========

2 个答案:

答案 0 :(得分:2)

htobe64返回类型uint64_t,不长。值18446744073709551484是两者的补码-132的无符号64位表示形式。 = 0xffffffffffffff7c

答案 1 :(得分:2)

函数cout << "be64toh = " << be64toh(b) << endl;的行be64toh接受并返回base64_t,因此cout将位序列打印为无符号。因此,您将看到位序列的无符号解释。通常,带符号的数字以2的恭维方法表示(尽管它可能因硬件而异)。它适用于正数,因为带符号的位是0,因此位序列是相同的。但是如果是负数,则带符号的位(最左边的位)为1,如果将这样的位序列解释为无符号的整数,它将为您带来巨大的数字。

如果用以下示例替换语句:

cout << "be64toh = " << (long) be64toh(b) << std::endl;

将整数重新解释为带正负号(默认情况下,long为带正负号),那么您将能够看到所需的结果。

因此endian转换没有问题,这只是打印例程根据变量类型解释的方式。