变量重识别引发无限循环:为何移除while语句中int后代码正常执行一次?
嘿,这两个无限循环的坑本质上都是变量作用域和遮蔽规则在搞鬼,我来给你掰扯清楚~
一、变量重识别(遮蔽)导致的无限循环
首先得搞懂什么是变量遮蔽:当你在一个内层作用域里声明了和外层同名的变量时,内层变量会“抢走”外层变量的可见性——在这个内层作用域里,你能访问到的只有内层的那个变量,外层的就被“藏”起来了。如果这个外层变量刚好是控制循环终止的关键,那循环就会直接失控,无限跑下去。
举个直观的例子(用JavaScript):
function runLoop() { let count = 0; while (count < 3) { // 这里用let声明了一个新的count,完全遮蔽了外层的控制变量 let count = 1; console.log("循环ing..."); } } runLoop();
这段代码会无限打印“循环ing...”,原因很简单:循环条件判断的是外层的count(值一直是0,永远满足count < 3),而循环块里的count是个全新的变量,修改它对控制循环的那个count半毛钱影响都没有,循环自然停不下来。
核心原因就是:控制循环终止的变量被内层同名变量遮蔽,导致它永远无法被修改到,循环条件持续为真。
二、while语句内保留int引发的无限循环(移除int则正常执行)
这个其实是上面变量遮蔽问题的一个具体场景,咱们拿C/C++代码来拆解最清楚:
无限循环的版本:
int num = 0; while (num < 1) { int num = 1; // 罪魁祸首就是这个int声明 printf("本以为只跑一次?结果无限循环!\n"); }
正常执行一次的版本:
int num = 0; while (num < 1) { num = 1; // 去掉int,直接修改外层的控制变量 printf("跑一次就退出啦~\n"); }
为啥会这样?
- 在C/C++里,
while的{}是一个块级作用域,里面用int声明的num是一个全新的局部变量,直接遮蔽了外层的同名num。 - 循环条件
num < 1判断的是外层的num,它的初始值是0,而且在循环块里根本没被碰过——你修改的是块内那个新的num,和控制循环的那个变量完全没关系。 - 所以每次循环都满足
num < 1,循环永远停不下来。 - 当你去掉
int后,代码直接修改的是外层的num,把它改成1,下一次循环条件判断1 < 1不成立,循环就正常终止了,自然只执行一次。
说白了就是:加int等于创建了一个“冒牌”的同名变量,根本碰不到控制循环的那个“正主”;去掉int才是真正修改了控制循环的变量,让循环能正常结束。
内容的提问来源于stack exchange,提问作者evan holt
相关产品推荐
相关产品推荐

