无符号长整型的负值

6
请看下面的简单代码:
#include <iostream>
#include <stdlib.h>

using namespace std;


int main(void)
{
    unsigned long currentTrafficTypeValueDec;
    long input;
    input=63;
    currentTrafficTypeValueDec = (unsigned long) 1LL << input; 
    cout << currentTrafficTypeValueDec << endl;
    printf("%u \n", currentTrafficTypeValueDec);
    printf("%ld \n", currentTrafficTypeValueDec);
    return 0;
}

为什么 printf() 显示当前的 currentTrafficTypeValueDec(无符号长整型)值为负数?

输出结果如下:

9223372036854775808
0
-9223372036854775808 

可能是 https://dev59.com/tkrSa4cB1Zd3GeqPXpvU 的重复问题。 - user202729
6个回答

19

%d 是有符号格式化器。将 currentTrafficTypeValueDec(2的63次方)的比特位重新解释为signed long,会得到一个负值。因此,printf() 打印出一个负数。

也许您想使用 %lu


14
您向printf函数传递了一个无符号值,而格式说明符却表示它应该是带符号的。

有趣的表达方式 :) - Tim

5

因为你将1移位到变量的符号位。当你将其作为有符号值打印时,它是负数。


5

位运算的乐趣...

cout 将数字打印为无符号长整型,所有 64 位都是有效的,并且以无符号二进制整数的形式打印(我认为这里的格式应该是 %lu)。

printf(%u ... 将输入视为普通的无符号整数(32 位?)。这会导致第 33 到 64 位的位被截断 - 变成零。

printf(%ld ... 将输入视为 64 位有符号数字,并将其按照此类数字打印出来。

你可能会对最后一个printf感到困惑的是,它给出了与cout相同的绝对值,但带有一个负号。当将其视为无符号整数时,所有64位都对生成整数值至关重要。然而,对于有符号数字,第64位是符号位。当符号位被设置(如在您的示例中)时,它表示剩余的63位应该被视为在2's compliment中表示的负数。正数只需将它们的二进制值转换为十进制即可打印。但对于负数,以下情况发生:打印一个负号,将第1到63位与二进制“1”位进行XOR运算,将结果加1并打印无符号值。通过丢弃符号位(第64位),您最终得到63个'0'位,与'1'位进行XOR运算会得到63个'1'位,再加上+1,整个过程就会翻转,从而得到一个无符号整数,其中第64位设置为'1',其余位设置为'0' - 这与您使用cout得到的完全相同,但作为负数。
一旦你理解了上述解释的正确性,你也应该能够理解this的意义。

2

变量本身不带有其类型信息。您需要在printf中指定其类型。尝试使用以下代码:

printf("%lu \n", currentTrafficTypeValueDec);

因为ld代表长符号,这是不正确的。


0
你正在打印%ld,或者是一个长的带符号十进制数。这就是为什么它会返回一个负值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接