为啥'continue'语句忽略'while'循环中的循环计数器增量,而不是'for'循环?

Posted

技术标签:

【中文标题】为啥\'continue\'语句忽略\'while\'循环中的循环计数器增量,而不是\'for\'循环?【英文标题】:Why is 'continue' statement ignoring the loop counter increment in 'while' loop, but not in 'for' loop?为什么'continue'语句忽略'while'循环中的循环计数器增量,而不是'for'循环? 【发布时间】:2013-05-11 23:35:40 【问题描述】:

如果我在while 循环中使用continue,为什么它倾向于进入无限循环,但在for 循环中工作正常? 如果我在continue 之后使用循环计数器增量i++,它会在while 循环中被忽略,但如果它在for 循环中,它会起作用。

如果continue 忽略后续 语句,那么为什么不忽略for 循环的第三条语句,其中包含计数器增量i++for 循环的第三条语句 subsequentcontinue 是否也应该被忽略,因为for 循环的第三条语句是在 之后执行的循环体?

while(i<10)   //causes infinite loop

    ...
    continue
    i++
    ...


for(i=0;i<10;i++)  //works fine and exits after 10 iterations

    ...
    continue
    ...

【问题讨论】:

查看输出程序集,您会发现 for 循环并没有像您想象的那样扩展。 问:如果将continue AFTER i++ 放入“while”循环会发生什么?问:你明白初始化、增量和条件都是你的“for”循环中同一个结构的一部分吗?它们总是被执行,与循环内发生的事情无关? Thokchom,我建议你找一些比 MS 提供的更好的文档 :-) MS 是信任的代名词?我拒绝发表评论 :-) 无论是错误的还是被误解的,我都会留给你决定。它确实将控制权传递回for主体的第一条语句,但在首先执行后期操作之后。 Thokchom,我认为这是一个错字,条件表达式是中间那个,所以我怀疑他们的意思是“......导致 for 语句的 third 表达式待评估”。 【参考方案1】:

因为continue 回到循环的开头。使用for,后操作i++是循环控制的一个整体部分,在循环体重新启动之前执行。

对于whilei++ 只是循环体中的另一个语句(与a = b 之类的语句没有什么不同),如果您在到达之前continue 将被跳过。

【讨论】:

我死定了!!微软网站还有一个自相矛盾的描述。上面写着A continue statement in a for statement causes the first expression of the for statement to be evaluated--msdn.microsoft.com/en-IN/library/0ceyyskb(v=vs.80).aspx你能解释一下控制权是如何进入for循环的第一条语句的吗? @Thokchom,鉴于该页面上指向for 声明的链接甚至没有描述第三部分(操作后),我将依靠其他东西来学习. @Thokchom 该页面上的描述严重损坏。他们为明确描述for 声明的页面提供的链接是准确的。您可能需要考虑提交更正请求。 @NikBougalis 不敢相信微软网站会如此不专业。 @Thokchom 放松,错误发生了。尤其是当您必须维护一个内容与 MSDN 一样多的网站时。【参考方案2】:

原因是continue 语句会短路循环体中跟在它后面的语句。由于您编写while 循环的方式在continue 语句之后有增量语句,因此它会短路。您可以通过更改 while 循环来解决此问题。

很多教科书声称:

for (i = 0; i < N; ++i) 
    /*...*/

相当于:

i = 0;
while (i < N) 
    /*...*/
    ++i;

但是,实际上,真的是这样的:

j = 0;
while ((i = j++) < N) 
    /*...*/

或者,更迂腐一点:

i = 0;
if (i < 10) do 
    /*...*/
 while (++i, (i < 10));

这些更等效,因为现在如果while 的主体有一个continue,增量仍然会发生,就像在for 中一样。后一种选择只在迭代完成后执行增量,就像for 一样(前者在迭代之前执行增量,推迟到迭代之后将其保存在i 中)。

【讨论】:

@Thokchom:不同之处在于,最后一个公式将允许while 循环中的continue 继续递增。 哦..当一个人想要continue 不要忽略增量时会很方便。好技巧! +1 @Thokchom:谢谢,我更新了答案,让我的意图更加清晰。【参考方案3】:

i 的增量是在 continue 之后,所以它永远不会被执行

while(i<10)   //causes infinite loop

.........
continue
i++
......

【讨论】:

【参考方案4】:

在任何循环中,continue 将执行移回循环顶部,在 continue 语句之后不执行任何其他指令

在这种情况下,总是执行 for 循环的定义(根据标准 C),而 i++;语句未执行,因为它出现在 continue 语句之后。

【讨论】:

【参考方案5】:

因为 for 的第三部分总是被执行。

【讨论】:

这个答案应该在字典中的“重言式”下链接。【参考方案6】:

continue 语句将控制跳转到循环当前迭代中的语句末尾,即它跳过当前迭代中语句的执行并移动到循环的下一个迭代。

使用while 循环,continue 语句会导致控制到达语句的末尾(包括增量语句),从而导致循环永远继续。

使用for 循环,continue 语句将控制跳转到语句末尾并执行增量语句(在for 循环中,增量语句被认为与循环体中编写的语句是分开的)。

【讨论】:

【参考方案7】:

for 循环包含条件语句和增量,因此当条件满足时,它会执行 for 循环内的语句,但如果编写 continue 语句,它将再次到达 for 循环的第一行,即增量和条件语句检查,如果满意,则再次执行。 对于 while 循环,它只检查条件语句,如果条件满足,则执行 while 循环中的语句。 所以 continue 不会在它之后执行任何行。因此你的条件每次都满足并进入无限循环。

【讨论】:

【参考方案8】:

continue 绕过块的其余部分,如果满足循环的条件,则从块的顶部重新开始。

下一个问题是:“那我该怎么办?” 我能想到的答案有两个。

例子:

void foo ()

    size_t i = 0;
    do
    
        /*...*/
        if ( /*...*/ )
        
            /*...*/
            continue;
        
        /*...*/
        i++;
     while ( /* loop conditional */ );

解决方案 #1: 手动递增

void foo ()

    size_t i = 0;
    do
    
        /*...*/
        if ( /*...*/ )
        
            /*...*/
            i++;
            continue;
        
        /*...*/
        i++;
     while ( /* loop conditional */ );

解决方案 #2:goto* 的唯一有效应用程序

void foo ()

    size_t i = 0;
    do
    
        /*...*/
        if ( /*...*/ )
        
            /*...*/
            goto foo_next;
        
        /*...*/
foo_next:
        i++;
     while ( /* loop conditional */ );

goto 在这种情况下是有效的,因为在两个地方的递增在技术上是相同的指令。当 per-iteration-volatile 变量更复杂时,此解决方案尤其重要;例如,设置多个变量或使用方程式或函数修改值。

在单个递增或递减语句的情况下,解决方案 #1 可能证明是有利的;但是,应该注意的是:如果在这样的实现之后修改了代码,必须记住更新语句的两个实例(这可能容易出现错误,特别是如果修改发生在很长一段时间后** )。因此,我强烈推荐解决方案 #2。

*有些人认为任何和所有使用goto 都是不好的做法。我建议您自己决定,并留给您:google for "c goto bad"

**一条提醒这种必要性的评论可能就足够了,但是——如果我的建议被遵循——每迭代易失性变量被限制在一个语句中。我引用:

从不评论一行

-Linus Torvalds(来源:http://yarchive.net/comp/linux/coding_style.html

【讨论】:

以上是关于为啥'continue'语句忽略'while'循环中的循环计数器增量,而不是'for'循环?的主要内容,如果未能解决你的问题,请参考以下文章

break语句与continue语句

使 continue 语句在 do while 循环中工作

continue语句的作用

3.2.2 break 与 continue 语句

java 为啥使用continue会使程序错误

python3-while与continue