为啥'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
循环的第三条语句 subsequent 到 continue
是否也应该被忽略,因为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++
是循环控制的一个整体部分,在循环体重新启动之前执行。
对于while
,i++
只是循环体中的另一个语句(与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'循环?的主要内容,如果未能解决你的问题,请参考以下文章