【问题标题】:Why does the following code go into an infinite loop?为什么下面的代码会进入无限循环?
【发布时间】:2012-12-15 04:00:37
【问题描述】:

考虑以下代码:

const char *s = "a   b    c  d !";
const char *p = s;

top:for(; *p; p++) {
    switch(*p) {
    case 0x20: 
    case '\n': 
        goto top;
    default: 
        putchar(*p);
    }
}

有人可以解释为什么当*pNULL 时它会进入无限循环而不是停止吗?我想到了以下几点:当*p0x20\n 时,再次转到循环的开头,因为它测试条件并计算表达式p++。所以,我看不出它无限循环的原因,或者我真的不明白goto 语句和labels 在 C 编程语言中是如何工作的。

【问题讨论】:

标签: c for-loop infinite-loop goto


【解决方案1】:

当你goto top时,p++没有被执行,因为for循环又从头开始了。然后你又goto top。然后再一次。然后再一次。并且永远。

如果您希望增量起作用,请使用 continue 而不是 goto。或者,更好的是,做一些更清晰的事情:

for(p = s; *p != '\0'; p++) {
    switch(*p) {
    case 0x20:
    case '\n':
        // Do nothing.
        break;

    default: 
        putchar(*p);
    }
}

哦,顺便说一句,避免像瘟疫一样的 goto 声明。除非您以自动方式生成 C 代码并且它不应该是人类可读的,否则goto 几乎不是一个好主意。

【讨论】:

  • 为什么p++没有被执行?和*p 是不是也一样?
  • @Jack *p被执行,只跳过p++,因为没有到达循环的结尾。
  • @Jack 因为在 for 循环的第一次迭代中,从不执行递增-递减;它仅在第一次迭代结束后执行。但是由于您 goto 到了 for 循环之前的位置,因此它无法执行增量。相反,for 语句再次从头开始 开始,进行另一个first 迭代。
  • 我今天发现的非常危险的事情。我从来不知道通过foo:for(;*p;p++) if(..)goto foo; 并不是所有迭代都被评估。那是 p 没有增加。非常感谢。
  • @Jack 你今天应该发现的想法是你根本不应该使用goto
【解决方案2】:

这样做

const char *s = "a   b    c  d !";
const char *p = s;

 for(; *p; p++) {
    switch(*p) {
    case 0x20: case '\n': continue;
    default: putchar(*p);
    }
  }

原因是,您的代码甚至没有完成一次迭代,因此 p++ 永远不会执行。当您继续而不是使用标签时,它会算作一次完整的迭代。

【讨论】:

    【解决方案3】:
    const char *s = "a   b    c  d !";
    const char *p = s;
    
    top:
    for(; *p; p++) {
        switch(*p) {
        case 0x20: 
        case '\n': 
            p ++;
            goto top;
        default: 
            putchar(*p);
        }
    }
    

    您必须在goto top; 之前使用p ++;,因为转到top: 意味着您正在重新启动循环。

    【讨论】:

    • 使用goto 不是一个好习惯,当我必须处理错误情况时我使用goto
    猜你喜欢
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    • 2021-09-18
    • 2020-01-13
    • 2014-02-13
    • 2011-04-19
    • 1970-01-01
    相关资源
    最近更新 更多