【发布时间】:2012-04-15 22:21:02
【问题描述】:
正如问题标题所示,将 2^31 分配给有符号和无符号 32 位整数变量会产生意想不到的结果。
这是我制作的短程序(C++),看看发生了什么:
#include <cstdio>
using namespace std;
int main()
{
unsigned long long n = 1<<31;
long long n2 = 1<<31; // this works as expected
printf("%llu\n",n);
printf("%lld\n",n2);
printf("size of ULL: %d, size of LL: %d\n", sizeof(unsigned long long), sizeof(long long) );
return 0;
}
这是输出:
MyPC / # c++ test.cpp -o test
MyPC / # ./test
18446744071562067968 <- Should be 2^31 right?
-2147483648 <- This is correct ( -2^31 because of the sign bit)
size of ULL: 8, size of LL: 8
然后我向它添加了另一个函数p():
void p()
{
unsigned long long n = 1<<32; // since n is 8 bytes, this should be legal for any integer from 32 to 63
printf("%llu\n",n);
}
在编译和运行时,这让我更加困惑:
MyPC / # c++ test.cpp -o test
test.cpp: In function ‘void p()’:
test.cpp:6:28: warning: left shift count >= width of type [enabled by default]
MyPC / # ./test
0
MyPC /
为什么编译器会抱怨左移计数太大? sizeof(unsigned long long) 返回 8,那么这是否意味着 2^63-1 是该数据类型的最大值?
让我印象深刻的是,也许 n*2 和 n
void s()
{
unsigned long long n = 1;
for(int a=0;a<63;a++) n = n*2;
printf("%llu\n",n);
}
这给出了正确的 2^63 值作为输出,即9223372036854775808(我使用 python 验证了它)。但是左撇子有什么问题呢?
算术左移 n 相当于乘以 2n (前提是值不溢出)
-- 维基百科
该值没有溢出,只有一个减号会出现,因为该值为 2^63(所有位都已设置)。
我仍然无法弄清楚左移发生了什么,有人可以解释一下吗?
PS:这个程序是在运行 linux mint 的 32 位系统上运行的(如果有帮助的话)
【问题讨论】:
-
这应该是
unsigned long long n = 1ULL<<31; -
天哪!有这么容易吗?!为什么我没有想到。无论如何,是的 1ULL
标签: c++ bit-shift unsigned-integer