我有这段代码
int a = 1;
while(1) {
a<<=1;
cout<<a<<endl;
}
在输出中,我得到了
.
.
536870912
1073741824
-2147483648
0
0
为什么我没有达到INT_MAX?除了这一点,究竟发生了什么?
答案 0 :(得分:12)
你有一个签名的int,所以数字是两个补码。这就是发生的事情
00..01 = 1
00..10 = 2
[...]
01..00 = 1073741824
10..00 = -2147483648 // Highest bit to one means -01..11 - 1 = -(2^31)
00..00 = 0
您无法达到INT_MAX,最多只有2^30
。
正如评论中所指出的,c ++标准不强制执行2的补码,因此这些代码在其他机器中的行为可能不同。
答案 1 :(得分:7)
来自ISO / IEC 14882:2011条款5.8 / 2
E1的值<&lt; E2是E1左移E2位位置;空位是零填充的。如果E1具有无符号类型,则结果的值为E1×2 E2 ,比结果类型中可表示的最大值减少一个模数。否则,如果E1具有有符号类型和非负值,并且在结果类型中可以表示E1×2 E2 ,那么这就是结果值;否则,行为未定义
答案 2 :(得分:2)
根据C ++标准:
如果右操作数为负数,或大于或等于提升左操作数的位长度,则行为未定义
在左边移动数字的例子中,空出的位是零填充的。如您所见,您的所有数字都是均匀的。这是因为最低位填充为零。你应该写:
a = ( a << 1 ) | 1;
如果你想获得INT_MAX
。循环也应检查数字是否为正。
答案 3 :(得分:2)
看看这个(参考)[http://www.cplusplus.com/reference/climits/]:假设INT_MAX == 2^15-1
,按照你的方式进行循环,你将获得2^14
,2^15
和2^16
,但2^15-1
,永远不会。但INT_MAX不同(请参阅参考号or greater
),在您的机器中尝试此操作:
#include<climits>
#include<iostream>
int main(){
int a = 1;
int iter = 0;
std::cout << "INT_MAX == " << INT_MAX << " in my env" << std::endl;
while(1) {
a <<=1;
std::cout << "2^" << ++iter << "==" << a << std::endl;
if((a-1) == INT_MAX){
std::cout << "Reach INT_MAX!" << std::endl;
break;
}
}
return 0;
}
了解如何形成INT_MAX,2^exp - 1
。