在阅读其他人的代码时,我看到了一些非常奇怪的for
循环。我一直在尝试在for
中搜索C
循环的完整语法说明,但这很难,因为单词“for
”出现在不相关的句子中,使搜索几乎不可能谷歌有效。
在阅读this thread之后,我想到了这个问题,这让我再次感到好奇。
此处for
:
for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);
在中间条件下有一个逗号分隔两段代码,这个逗号有什么作用?我理解右边的逗号,因为它同时生成a>>=1
和b<<=1
。
但是在循环退出条件下,会发生什么?它会在p==0
,a==1
或两者都发生时退出吗?
如果有人能帮助我理解这一点并且可能指向完整的for
循环语法描述,那就太棒了。
答案 0 :(得分:131)
逗号不包含for循环;它是逗号运算符。
x = (a, b);
首先执行a,然后执行b,然后将x设置为b的值。
for语法为:
for (init; condition; increment)
...
在某种程度上(暂时忽略continue
和break
)相当于:
init;
while (condition) {
...
increment;
}
所以你的for循环示例是(再次忽略continue
和break
)等效于
p=0;
while (p+=(a&1)*b,a!=1) {
...
a>>=1,b<<=1;
}
其行为就像它一样(再次忽略continue
和break
):
p=0;
while (true) {
p+=(a&1)*b;
if (a == 1) break;
...
a>>=1;
b<<=1;
}
for循环的两个额外细节,它们不是简单转换为上面的while循环:
true
(除非break
,goto
或其他内容破坏循环,否则会导致无限循环。continue
就像是在增量之前转移到标签一样,不像while循环中的continue
会跳过增量。此外,有关逗号运算符的重要细节:它是一个序列点,如&&
和||
(这就是为什么我可以将它拆分为单独的语句并保持其含义完整)。< / p>
C99标准引入了本解释中前面未提及的几个细微差别(这对C89 / C90非常有用)。
首先,所有循环本身都是块。有效地,
for (...) { ... }
本身包裹在一对大括号中
{
for (...) { ... }
}
标准说:
ISO / IEC 9899:1999§6.8.5迭代语句
¶5迭代语句是一个块,其范围是其范围的严格子集 封闭的。循环体也是一个块,其范围是范围的严格子集 迭代语句。
这也在基本原理中用额外的括号组来描述。
其次,C99中的init
部分可以是(单个)声明,如
for (int i = 0; i < sizeof(something); i++) { ... }
现在,'围绕循环的'块自成一体;它解释了为什么变量i
无法在循环外访问。您可以声明多个变量,但它们必须都是相同的类型:
for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }
标准说:
ISO / IEC 9899:1999§6.8.5.3for语句
声明
for ( clause-1 ; expression-2 ; expression-3 ) statement
表现如下:表达式表达式-2是控制表达式 在每次执行循环体之前进行评估。表达式-3表达式为 在每次执行循环体后评估为void表达式。如果第1条是a 声明,它声明的任何变量的范围是声明的剩余部分 整个循环,包括其他两个表达式;它是按执行顺序到达的 在第一次评估控制表达之前。如果子句-1是表达式,那么它是 在第一次评估控制表达之前评估为空表达。 133)
可以省略子句-1和表达式-3。省略的表达式-2由a替换 非零常数。
133)因此,第1节指定循环的初始化,可能声明一个或多个变量用于 循环;控制表达式expression-2指定在每次迭代之前进行的评估, 这样循环的执行一直持续到表达式比较等于0;和表达-3 指定每次迭代后执行的操作(例如递增)。
答案 1 :(得分:8)
逗号只是分隔两个表达式,并且在C中允许正常表达式的任何地方都有效。这些按从左到右的顺序执行。最右边表达式的值是整个表达式的值。
for
循环由三部分组成,其中任何一部分也可能是空的;一个(第一个)在开始时执行,一个(第三个)在每次迭代结束时执行。这些部分通常分别初始化和递增计数器;但他们可以做任何事情。
第二部分是在每次执行开始时执行的测试。如果测试结果为false
,则循环中止。这就是它的全部内容。
答案 2 :(得分:5)
C style for循环包含三个表达式:
for (initializer; condition; counter) statement_or_statement_block;
这些部分中的每一部分都可以是您编写循环语言的有效表达式。这意味着它们可以更具创造性地使用。你想要事先做的任何事情都可以进入初始化程序,你想要做的任何事情都可以进入条件或计数器,直到循环没有正文的程度。
为实现这一点,逗号运算符非常方便。它允许您将表达式链接在一起以形成单个新表达式。大多数情况下,它在for循环中以这种方式使用,逗号运算符的其他含义(例如值赋值注意事项)起着次要的作用。
即使你可以通过创造性地使用语法来做聪明的事情 - 我会保持清醒,直到我找到真的这样做的理由。使用for循环播放代码高尔夫使代码更难以阅读和理解(和维护)。
维基百科也有一个不错的article on the for loop。
答案 3 :(得分:2)
for
循环中的所有内容都是可选的。我们可以初始化多个变量,我们可以检查多个条件,我们可以使用逗号运算符迭代多个变量。
以下for
循环将带您进入无限循环。检查条件时要小心。
for(;;)
答案 4 :(得分:0)
当我在for循环的“条件”部分中放入两个测试时,Gnu编译器声明了这个警告
warning: left-hand operand of comma expression has no effect
我真正想要的“条件”是两个带有“&amp;&amp;”的测试之间。根据康拉德的声明,只有逗号右边的测试才会影响条件。
答案 5 :(得分:-1)
for循环执行(;;)
的特定时间for循环的syntex
有(;;)
OR
for(initializer; condition; counter)
例如(rmv = 1; rmv&lt; = 15; rmv ++)
执行15次for block
1.首先初始化值因为启动值
(例如)rmv = 1或rmv = 2
2.第二个语句是测试条件是真还是假,条件为真时间执行for循环且条件为false终止为块,
例如i = 5; i <= 10条件为真
i=10;i<10 the condition is false terminate for block,
3.第三个是递增或递减
(例如)rmv ++或++ rmv