题
我已经看到了一些非常奇怪 for
循环的时候读的其他人的代码。我已经试图寻找一种完整的语法解释 for
循环在 C
但它是非常困难的,因为单词"for
"现在不相关的句子,使得几乎不可能搜索到了谷歌有效。
这个问题来到我的脑海之后读取 这个线程 这让我好奇了。
的 for
在这里:
for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);
在中间状况有一个逗号分开的两条码,这是什么逗号做的吗?逗号在右边我的理解,因为它使这两个 a>>=1
和 b<<=1
.
但是,在一个循环中退出条件,会发生什么?它不会退出的时候 p==0
, 时 a==1
或两者时发生的?
这将是巨大的,如果任何人能帮我了解这个也许我指的方向的一个完整的 for
环语法的描述。
解决方案
逗号不是唯一的循环;这是逗号操作员。
x = (a, b);
会做的第一a、b、然后设x的值b。
在语法是:
for (init; condition; increment)
...
其中有些(忽略 continue
和 break
现在)相当于:
init;
while (condition) {
...
increment;
}
所以你的循环的例子是(再次忽视了 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;
}
两个额外细节的循环,它们不在简化转换到一个循环:
- 如果条件是省略,它是总是
true
(导致一个无限的循环,除非一个break
,goto
, 或其他东西打破的循环)。 - 一个
continue
行为如同它是转到一个标签之前增加,与不同的一个continue
在同时循环,这将跳过增加。
此外,一个重要的细节约的逗号操作员:它是一个顺序点像 &&
和 ||
(这就是为什么我可以分为单独的语句,并保持其意义不变).
变化C99
C99标准引入了几个细微差别没有提到早些时候在这的解释(这是非常好的C89/C90).
第一,所有循环块在他们自己的权利。有效,
for (...) { ... }
是自己包裹在一双牙套
{
for (...) { ... }
}
该标准说:
ISO/IEC9899:1999年§6.8.5迭代的声明
¶5个迭代的声明是一个方框,其范围是一个严格的子集的范围 封闭区块。循环体也是一个方框,其范围是一个严格的子集的范围 迭代发言。
这也是中所述的理由在条款的额外设置的括号。
其次, init
部在C99可以是(一)《宣言》,作为在
for (int i = 0; i < sizeof(something); i++) { ... }
现在的'块包裹的循环进入其自己;这解释了为什么变 i
无法访问以外的循环。你可以宣布的多个变量,但他们必须全部同一类型:
for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }
该标准说:
ISO/IEC9899:1999年§6.8.5.3的声明
该声明
for ( clause-1 ; expression-2 ; expression-3 ) statement
行为如下:表表达-2的控制表达这是 之前评估每一执行的循环机构。表表达-3 评估为无效的表达之后,每一个执行的循环机构。如果条款-1是 《宣言》的保护范围的任何变量,它宣布为剩余的宣言和 整个循环,包括其他两种表达式;它达到了执行 之前的第一个评估控制的表达。如果条款-1是一种表达,这是 评估为无效的表达之前首先评估的控制表达。133)
这两个条款-1和表3中可以省略。一省略表达-2替换 非零恒定。
133) 因此,条款-1指定的初始化的循环,可能宣布一个或多个变量使用在 的循环;控制的表达,表达-2,指定一个评价之前作出的每一次迭代, 这样,执行的循环的继续,直到表达比较等于0;和表达-3 指定的操作(例如递增),之后执行的每一次迭代。
其他提示
逗号只是分隔两个表达式,并且在C中允许正常表达式的任何地方都有效。这些按从左到右的顺序执行。最右边表达式的值是整个表达式的值。
循环的 由三部分组成,其中任何部分也可以为空;一个(第一个)在开始时执行,一个(第三个)在每次迭代结束时执行。这些部分通常分别初始化和递增计数器;但他们可以做任何事情。
第二部分是在每次执行开始时执行的测试。如果测试产生 false
,则循环中止。这就是它的全部内容。
C式循环的由三个表达方式:
for (initializer; condition; counter) statement_or_statement_block;
- 初始化器运行一次,当时的循环的开始。
- 条件是检查之前的每一次迭代。循环的运行,长则将其认定为真实的。
- 计数器运行一次后每次迭代。
这些零件的每一个可以表达有效的语言编写的循环。这意味着他们可以使用更多的创造性。任何你想要做的事先可以进入初始化程序,任何你想要做的之间可以进入的状况或反,一直到这里的循环已经有身体了。
为了实现这一目标,逗号操作者有很方便的。它可以让你链表达在一起,形成一个单一的新的表达。大部分时间是用这种方式在一个循环,其他影响的逗号操作员(例如值分配的考虑因素)发挥次要的作用。
即使可以做聪明的事情,通过使用的语法创造性地-我能留下它直到我找到一个 真的 很好的理由这样做。播放的代码的高尔夫用的循环使得码更难于阅读和理解(以及维护).
维基百科有一个很好的 文章在环路 为好。
for
循环中的所有内容都是可选的。我们可以初始化多个变量,我们可以检查多个条件,我们可以使用逗号运算符迭代多个变量。
以下 for
循环将带您进入无限循环。检查条件时要小心。
for(;;)
当我在“条件”中进行两次测试时,Gnu编译器会发出此警告。 for循环的部分
warning: left-hand operand of comma expression has no effect
我真正想要的“条件”是什么两次测试是用“&amp;&amp;&amp;”进行的。之间。根据康拉德的声明,只有逗号右边的测试才会影响条件。
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