我离开INT_MAX后发生了什么?

时间:2014-02-02 15:32:11

标签: c++ bit-manipulation

我有这段代码

int a = 1;
while(1) {
    a<<=1;
    cout<<a<<endl;
}

在输出中,我得到了

.
.
536870912
1073741824
-2147483648
0
0

为什么我没有达到INT_MAX?除了这一点,究竟发生了什么?

4 个答案:

答案 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^142^152^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