当我离开int_max时,发生了什么

What is happening when I left shift beyond INT_MAX ?

本文关键字:发生了 什么 max 我离开 int      更新时间:2023-10-16

我有这个代码

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

在输出中,我得到

.
.
536870912
1073741824
-2147483648
0
0

为什么我不到达int_max?而实际上发生了什么?

您有一个签名的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的补充,因此该代码在其他机器中的行为可能有所不同。

来自ISO/IEC 14882:2011第5.8/2条

e1&lt;&lt;E2是E1左移E2位位置;腾空的位为零。如果E1具有无符号类型,则结果的值为E1×2 e2 ,减少了Modulo比结果类型中可表示的最大值多。否则,如果E1具有签名类型和非负值,并且E1×2 E2 在结果类型中表示可表示,则是结果值;否则,行为是未定义的

请看一下此(参考)[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

根据C 标准:

如果右操作数为负,或大于或等于晋升的左操作数

的长度,则行为是不确定的。

在您的示例中,当您移动左侧的数字时,空缺的位为零。如您所见,您的所有数字均为。这是因为最低位填充了零。你应该写:

a =  ( a << 1 ) | 1;

如果要获得INT_MAX。此外,循环应检查数字是否为正。