请参阅以下简单代码:
#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
答案 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
或长签名小数。这就是它返回负值的原因。