【问题标题】:Am I correct in figuring out why this while loop is infinite?我是否正确地弄清楚为什么这个while循环是无限的?
【发布时间】:2020-10-02 10:06:08
【问题描述】:

我写了一个简单的程序(包括在下面),它接受一个 5 位数字,反转并打印它。

#include <stdio.h>
#include <limits.h>
#include <math.h>
int main(void)
{
        unsigned short num, revnum, digit, count;
        count = 4;
        revnum = 0;
        fprintf(stdout, "Enter a five digit number in range [0 - %hu]: ", USHRT_MAX);
        fscanf(stdin, "%hu", &num);
        while (count >= 0) {
                digit = num % 10;
                num = num / 10;
                revnum += digit * pow(10, count);
                count--;
        }
        fprintf(stdout, "The number with digits reversed is %hu.\n", revnum);
        return 0;
}

但是,程序在运行时,在接受输入并将其存储在num 变量中后不会返回任何内容。它也没有崩溃/退出。 while 循环的主体没有任何问题,所以我怀疑是无限循环并编写了一个小程序,只是为了从类似的 while 循环中打印出 count 变量

#include <stdio.h>
int main(void)
{
        unsigned short count;
        count = 4;
        while (count >= 0) {
                printf("%hu", count);
                count--;
        }
        return 0;
}

这确实是一个infinite 循环......输出的一部分是:

...300653005530045300353002530015300052999529985299752996529955299452993529925299152990529895298852987529865298552984529835298252981529805297952978529775297652975529745297352972529715297052969529685296752966529655296452963529625296152960529595295852957529565295552954529535295252951529^C

我的假设是罪魁祸首是counttype,即unsigned short。因为这意味着它不能递减到 0 以下,所以最终的 count-- when count already == 0 将其值设置为 USHRT_MAX,因此永远不能终止循环。我说的对吗?

【问题讨论】:

  • 是的,count 不能为负,条件始终为真。我相信关于它如何不能是负面的细节是实现定义的,等待确认。
  • count 变量是unsigned,这意味着它总是大于或等于零。是的,你的假设是正确的。
  • 大多数编译器在对无符号值使用&gt;= 0 时会发出警告。
  • 在调用 gcc 时包含 -Wtype-limits-W 以获取此警告。

标签: c while-loop infinite-loop unsigned


【解决方案1】:

您的假设是正确的:作为您的变量 unsigned,它永远不会被评估为负数。

在您的情况下,如果您在 count 变量等于 0 时减少它,您会得到值 65535 (USHRT_MAX)。

简单的解决方案是去掉 unsigned 关键字:

short count = 4;

此解决方案最适合问题中提供的基本代码。无论如何,由于在“真实代码”中可能发生更改计数器类型不是一种选择,因此在递减之前检查count == 0 可能是解决方案(感谢@Elijan9):

while (true)
{
    /* ...; */
     if (count == 0)
        break;
    --count;
 }

【讨论】:

  • 或者坚持使用无符号并将计数与 0 进行比较,然后在循环中递减计数,例如while (true) { ...; if (count == 0) break; --count; }
  • @Elijan 当然,即使在这种特定情况下它可能会有点矫枉过正。此外,它可能不是实际代码,而只是 MRE
  • @Elijan9 我已经采纳了你的建议(并适当地奖励它),以防问题中的代码不是实际代码,而只是一个简化的 MRE。谢谢。
猜你喜欢
  • 2013-11-12
  • 2014-01-08
  • 2014-12-15
  • 2021-01-06
  • 2019-09-15
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
  • 2016-07-14
相关资源
最近更新 更多