带有负值的无符号长整数

时间:2010-03-16 15:45:07

标签: c++

请参阅以下简单代码:

#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(unsigned long)?

输出结果为:

9223372036854775808
0
-9223372036854775808 

6 个答案:

答案 0 :(得分:17)

%d是签名格式化程序。将currentTrafficTypeValueDec(2到63次幂)的位重新解释为signed long会给出负值。因此printf()会打印一个负数。

也许你想使用%lu

答案 1 :(得分:14)

你通过传递一个无符号值来欺骗printf,而格式规则说它将是一个签名的。

答案 2 :(得分:5)

因为您正在将1转换为变量的符号位。当您将其打印为有符号值时,它是否定的。

答案 3 :(得分:4)

有趣的比特......

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

printf(%u ...将输入视为普通的无符号整数(32位?)。这导致位33到64下降 - 留下零。

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

您可能会对上一个printf感到困惑的事情是,它提供与cout相同的绝对值,但带有减号。当作为无符号整数查看时,所有64位在产生整数值时都是重要的。但是对于带符号的数字,第64位是符号位。当符号位置位时(如您的示例所示),它表示剩余的63位将被视为2's compliment中表示的负数。只需将二进制值转换为十进制即可打印正数。但是对于负数,会发生以下情况:打印一个负号,XOR位1到63,二进制“1”位,将结果加1并打印无符号值。通过丢弃符号位(第64位),最终得到63'0'位,与'1'位进行异或,得到63'1'位,加上+1,整个事物翻转,得到一个带位的无符号整数64设置为'1',其余设置为'0' - 这与cout BUT相同,但为负数。

一旦你弄清楚为什么上面的解释是正确的,你也应该能够理解this

答案 4 :(得分:1)

变量本身不携带其类型。您指定printf其类型。尝试:

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

因为ld并且长期签名并不是真的。

答案 5 :(得分:0)

您正在打印%ld或长签名小数。这就是它返回负值的原因。