为什么这会导致无限循环?

Why this causes an infinity loop?

本文关键字:无限循环 为什么      更新时间:2023-10-16
for (unsigned u = 10; u >= 0; --u)
std::cout << u << std::endl;

我知道 unsigned 不能小于我预期的0它从 10 打印到 0,因为u >= 0

// WRONG: u can never be less than 0; the condition will always succeed
for (unsigned u = 10; u >= 0; --u)
std::cout << u << std::endl;

考虑一下当u0时会发生什么。在该迭代中,我们将打印0,然后在 for 循环中执行表达式。--u,该表达式从u中减去1。该结果 -1 不适合无符号值。与任何其他超出范围的值一样,-1将转换为无符号值。假设32位整数,则--u的结果,当u0,是4294967295

编写此循环的一种方法是使用 while 而不是 for。使用 while 可以让我们在打印值之前(而不是之后(递减:

unsigned u = 11; // start the loop one past the first element we want to print
while (u > 0) {
--u; // decrement first, so that the last iteration will print 0
std::cout << u << std::endl;
}


此循环从递减循环控制变量的值开始。在最后一次迭代中,u在进入循环时将为 1。我们将递减该值,这意味着我们将在此迭代中打印0。当我们下次在 while 条件下测试 u 时,它的值将是0,循环将退出。因为我们从 递减u,我们必须将您初始化为比我们要打印的第一个值大一个的值。因此,我们将您初始化为11,以便打印的第一个值10

每次迭代u递减。u最终被0u >= 0仍然持有true所以另一个迭代再次u欺骗。无符号整数环绕(因为无符号整数不能为负数(,你会得到u == numeric_limits<unsigned>::max,冲洗并重复。

如果你从另一个角度来思考这个问题,这一点就会变得清晰起来。

for 循环的条件是u >= 0。当这为 false 时,for 循环将停止循环。

如您所知,u不能小于 0。当你在它为 0 时递减它时,它将再次换行,所以u >= 0总是正确的。

所以u >= 0从来都不是假的。

所以 for 循环是无限的。

如果要打印 10 到 0,则可以只使用其他数据类型。

在代码块中

for (unsigned u = 10; u >= 0; --u)
std::cout << u << std::endl;

u是无符号整数,并尝试找到其范围,该范围为0 to 4294967295. 并且u>=0始终为真 所以条件永远不会失败,这会导致循环无限运行。

u = 10            ,  10 >=0     => true => prints 10
..
when u = 0             ,  0>=0       => true => prints 0
u = 4294967295    ,  4294967295 >=0 true ( it will not -1 > 0 as there is no -1 in the range of unsigned int )

同时,如果您旋转循环 10 次,请保持条件u>0

for (unsigned u = 10; u > 0; --u)
std::cout << u << std::endl;