为什么在while循环中对int原始类型进行递增不会无限循环

3
我有以下代码示例。
int i = 1;  

while(i != 0) {  
    i++;  
} 

我原本以为这个程序会一直运行下去,但实际上并没有。当我在 while 循环后打印变量时,输出了以下结果:

i value is 0.  

请问有人能告诉我到底发生了什么吗?


2
更重要的是,你为什么认为它应该导致内存问题?这里使用了哪些内存? - Hovercraft Full Of Eels
5
有人能告诉我到底发生了什么吗?-- 整数溢出。 - devnull
我本来以为这个程序会进入一个无限循环,但实际上并没有。如果你想要一个无限循环,可以使用 "while (true) {}"。 - pablosaraiva
2个回答

17

我本以为这将会无限循环,但它并没有。

不会的。最终,该值会再次变为0。

具体来说,它的逻辑执行方式如下:

1
2
3
...
2,147,483,646
2,147,483,647  
-2,147,483,648  // Integer overflow => wrapping
-2,147,483,647
...
-3
-2
-1
0

如果整数相加溢出,则结果是在某个足够大的二进制补码格式中表示的数学总和的低阶位。 如果发生溢出,则结果的符号与两个操作数值的数学总和的符号不同,然后循环将结束。

引用自JLS第15.18.2节:

如果整数相加溢出,则结果是在某个足够大的二进制补码格式中表示的数学总和的低阶位。 如果发生溢出,则结果的符号与两个操作数值的数学总和的符号不同。

此代码没有任何内存问题,因为它不执行任何分配 - 它只是在堆栈上完全递增一个局部变量。

现在这是否实际上做到了这一点是另一回事 - 如果JIT能够在不执行每次迭代的情况下找出行为,它可以将其优化掉 - 但这是一个实现细节。 重要的是理解行为背后的逻辑。


非常感谢。是的,我太傻了,以为会出现堆内存异常,而不是栈溢出错误。但现在我知道为什么它没有进入无限循环,也知道为什么没有出现错误。 - Srikanth Ganji
@SrikanthGanji:你为什么会期望栈溢出?在循环内部不再分配堆栈内存 - 它只是用另一个值替换一个值。 - Jon Skeet

4

Int是一个int: 对于每个i,如果iint,那么i+1也是int。一个int始终是32位,它永远不需要更大的容器。

最后,你的循环不是无限的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接