看似无限的'for'循环

A 'for' loop that appears to be practically infinite

本文关键字:for 循环 无限      更新时间:2023-10-16

我目前正在调试一些代码,我遇到了这一行:

for (std::size_t j = M; j <= M; --j)

(由我的老板写,正在度假。)

对我来说真的很奇怪。

它做什么?对我来说,它看起来像一个无限的循环。

std::size_t由C 标准保证为unsigned类型。而且,如果您将unsigned类型从0降低,则标准保证这样做的结果是该类型的最大值。

包裹的环值总是大于或等于M 1 ,因此循环终止。

因此,当应用于unsigned类型时,j <= M是一种方便的方式,说"将循环运行到零,然后停止"。

诸如运行j之类的替代方案比您想要的大,甚至使用 slide Operator for (std::size_t j = M + 1; j --> 0; ){存在,尽管需要更多键入,但可以说更清楚。我想一个缺点(除了在首次检查中产生的令人困惑的效果以外)是,它不能很好地移植到没有未签名类型的语言中,例如Java。

还请注意,您的老板从unsigned集中选择了"借用"可能的值的方案:在这种情况下,M设置为std::numeric_limits<std::size_t>::max()将没有正确的行为。实际上,在这种情况下,循环是无限的。(这是您要观察的吗?)您应该在代码中插入该效果的评论,甚至可能在该特定条件下断言。


1 M不为 std::numeric_limits<std::size_t>::max()

您的老板可能是尝试要做的是从 M降低到零(包括零),对每个数字执行一些操作。

不幸的是,有一个边缘案例,它确实会给您一个无限的循环,其中M是您可以拥有的最大size_t值。而且,尽管当您从零减少零时,它的定义很好,但我坚持认为代码本身就是草率思维的一个例子,尤其是因为没有老板的缺点而有一个完美的解决方案。

更安全的变体(在我看来,在保持严格范围限制的同时更可读)将是:

{
    std::size_t j = M;
    do {
        doSomethingWith(j);
    } while (j-- != 0);
}

举例说明,请参见以下代码:

#include <iostream>
#include <cstdint>
#include <climits>
int main (void) {
    uint32_t quant = 0;
    unsigned short us = USHRT_MAX;
    std::cout << "Starting at " << us;
    do {
        quant++;
    } while (us-- != 0);
    std::cout << ", we would loop " << quant << " times.n";
    return 0;
}

这与unsigned short基本上是同一件事,您可以看到它的过程每个单个值:

Starting at 65535, we would loop 65536 times.

在上述代码中替换do..while循环基本上的工作将导致无限循环。尝试一下,然后查看:

for (unsigned int us2 = us; us2 <= us; --us2) {
    quant++;
}