C 为什么是';继续';语句忽略';而';循环,但不在';对于';环
如果我在C 为什么是';继续';语句忽略';而';循环,但不在';对于';环,c,loops,for-loop,while-loop,continue,C,Loops,For Loop,While Loop,Continue,如果我在while循环中使用continue,但在for循环中运行良好,为什么它会进入无限循环? 循环计数器增量i++在中被忽略,而循环中,如果我在continue之后使用它,它将被忽略,但如果它在for循环中,它将起作用 如果continue忽略后续语句,那么它为什么不忽略for循环的第三条语句,其中包含计数器增量i++?鉴于for循环的第三条语句是在循环体之后执行的,因此for循环的第三条语句不也是继continue之后的第三条语句吗 while(i<10) //causes in
while
循环中使用continue
,但在for
循环中运行良好,为什么它会进入无限循环?循环计数器增量
i++
在中被忽略,而循环中,如果我在continue
之后使用它,它将被忽略,但如果它在for
循环中,它将起作用
如果continue
忽略后续语句,那么它为什么不忽略for
循环的第三条语句,其中包含计数器增量i++
?鉴于for
循环的第三条语句是在循环体之后执行的,因此for
循环的第三条语句不也是继continue
之后的第三条语句吗
while(i<10) //causes infinite loop
{
...
continue
i++
...
}
for(i=0;i<10;i++) //works fine and exits after 10 iterations
{
...
continue
...
}
while(i因为for的第三部分总是被执行。您的i
增量是在continue之后,所以它永远不会被执行
while(i<10) //causes infinite loop
{
.........
continue
i++
......
}
while(i在任何循环中,continue将执行移回循环的顶部,在continue语句之后不执行任何其他指令
在这种情况下,始终执行for循环的定义(根据标准C),而i++;语句不会执行,因为它位于continue语句之后。因为continue
返回循环的开头。对于for
,post操作i++
是循环控件的一个组成部分,在循环体重新启动之前执行
使用while
,i++
只是循环体中的另一个语句(与a=b
没有什么不同),如果在到达它之前continue
,则跳过。原因是continue
语句将使循环体中紧跟其后的语句短路。由于编写while
循环时,在continue
语句之后有increment语句,因此它会短路。您可以n通过更改while
循环来解决此问题
许多教科书声称:
for (i = 0; i < N; ++i) {
/*...*/
}
(i=0;i{
/*...*/
}
相当于:
i = 0;
while (i < N) {
/*...*/
++i;
}
i=0;
而(i
但事实上,这就像:
j = 0;
while ((i = j++) < N) {
/*...*/
}
j=0;
而((i=j++)
或者,更迂腐一点:
i = 0;
if (i < 10) do {
/*...*/
} while (++i, (i < 10));
i=0;
如果(i<10)do{
/*...*/
}而(++i,(i<10));
这两种方法更为等效,因为现在如果的主体在时有一个continue
,那么增量仍然会出现,就像在for
中一样。后者仅在迭代完成后执行增量,就像for
(前者在迭代之前执行增量,将其保存在i
中,直到迭代之后).continue
语句将控件跳到循环当前迭代中语句的末尾,即跳过当前迭代中语句的执行,并移动到循环的下一个迭代
使用while
loop,continue
语句使控制到达语句的末尾(包括increment语句),从而使循环永远继续
使用for
循环,continue
语句将控件跳到语句末尾并执行增量语句(在for
循环中,增量语句被视为与写在循环体中的语句分离).for循环保存条件语句和增量,因此当条件满足时,它将执行for循环中的语句,但如果写入continue语句,它将再次到达for循环的第一行,即条件语句的增量和检查,如果满足,则再次进入执行。
对于while循环,它只检查条件语句,如果条件满足,则执行while循环中的语句。
所以continue不会在它之后执行任何一行。因此,您的条件每次都满足,并进入无限循环。continue
绕过块的其余部分,如果满足循环的条件,则从块的顶部重新开始
下一个问题是:“那我该怎么办?”
我能想到两个答案
例如:
解决方案#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
在这种情况下是有效的,因为两个位置的增量在技术上是相同的指令。当每次迭代的可变变量更复杂时,此解决方案尤其相关;例如,设置多个变量或使用方程或函数修改值
对于单个递增或递减语句,解决方案#1可能是有利的;但是,应该注意的是:如果在这样的实现之后修改了代码,那么必须记住更新语句的两个实例(这可能容易出现错误,特别是如果修改在一段较长的时间之后发生**)。因此,我高度推荐解决方案#2
*考虑使用和使用<代码> Goto 不好的练习。我建议你自己决定,留给你这个:
**提醒这一必要性的注释可能就足够了,但是——如果遵循了我的建议——中的每次迭代可变变量仅限于一条语句。我引用:
从来没有理由评论一行
-Linus Torvalds(source:)看看输出程序集,你会发现for循环并不是按照你的想法展开的。Q:如果你在while循环中i++
之后加上continue,会发生什么?Q:你知道初始化、增量和条件都是同一个构造的一部分
void foo ()
{
size_t i = 0;
do
{
/*...*/
if ( /*...*/ )
{
/*...*/
goto foo_next;
}
/*...*/
foo_next:
i++;
} while ( /* loop conditional */ );
}