C中有什么完整的“for”循环语法(以及其他的兼容的情况)?

阅读其他人的代码时,我看到了一些非常奇怪for循环。 我一直在尝试在Cfor循环search完整的语法解释,但是这非常困难,因为单词“ for ”出现在不相关的句子中,使得search几乎不可能对Google有效。

这个问题出现在我的脑海,读了这个线程 ,让我很好奇。

在这里:

 for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1); 

在中间情况下,用逗号隔开这两个代码,这个逗号是干什么的? 我知道右边的逗号,它使得a>>=1b<<=1

但在循环退出条件下,会发生什么? 当p==0 ,当a==1或两者都发生时它会退出吗?

如果有人能够帮助我理解这一点,那将是非常好的,也许可以指向一个完整for循环语法描述。

逗号不是排除循环; 它是逗号运算符。

 x = (a, b); 

先做a,然后b,然后把x设为b的值。

for语法是:

 for (init; condition; increment) ... 

这是有点(忽略continuebreak现在)相当于:

 init; while (condition) { ... increment; } 

所以你的循环例子是(再次忽略continuebreak )相当于

 p=0; while (p+=(a&1)*b,a!=1) { ... a>>=1,b<<=1; } 

这就好像是(再次忽略continuebreak ):

 p=0; while (true) { p+=(a&1)*b; if (a == 1) break; ... a>>=1; b<<=1; } 

for循环的两个额外的细节没有被简化为上面的while循环:

  • 如果条件被省略,它总是true (导致无限循环,除非breakgoto ,或者别的什么东西打断循环)。
  • continue行为,就好像是在增量之前到达标签的转移,而不像while循环中的跳过增量的继续。

此外,关于逗号运算符的一个重要细节:它是一个序列点,像&&|| (这就是为什么我可以将它拆分成单独的语句并保持其意义完整)。


C99中的变化

C99标准引入了一些前面没有提到的细节(这对C89 / C90非常有用)。

首先,所有的循环本身都是块。 有效,

 for (...) { ... } 

本身是用一对括号包裹的

 { for (...) { ... } } 

标准说:

ISO / IEC 9899:1999§6.8.5迭代声明

¶5迭代语句是一个块,其范围是其封闭块的范围的严格子集。 循环体也是一个块,其作用域是迭代语句范围的严格子集。

理论中也用额外的大括号来描述这一点。

其次,C99中的init部分可以是一个(单个)声明,如in

 for (int i = 0; i < sizeof(something); i++) { ... } 

现在,“环绕的块”进入其自身; 它解释了为什么i不能在循环之外访问variables。 您可以声明多个variables,但它们必须全部是相同的types:

 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 

performance如下:expression式expression式-2是在每次执行循环体之前计算的控制expression式。 在每次执行循环体之后,expression式-3被评估为空expression式。 如果子句-1是一个声明,那么声明的任何variables的作用域就是声明的剩余部分和整个循环,包括其他两个expression式; 在控制expression式的第一次评估之前按照执行顺序达到。 如果子句-1是一个expression式,则在对控制expression式进行第一次评估之前,它将被评估为一个无效expression式。 133)

子句1和expression式3都可以省略。 省略的expression式-2被非零常量替代。

因此,子句1指定了循环的初始化,可能会声明一个或多个用于循环的variables; 控制expression式expression式-2指定在每次迭代之前进行的评估,使得循环的执行继续直到expression式比较等于0; 而expression-3指定每次迭代之后执行的操作(例如递增)。

C ++允许重载逗号运算符。 认真。

逗号只是分隔两个expression式,并且在允许正常expression式的C中的任何地方都是有效的。 这些按从左到右的顺序执行。 最右边的expression式的值是整个expression式的值。

for循环由三部分组成,其中任何一部分也可以是空的; 一个(第一个)在开始时执行,一个(第三个)在每个迭代结束时执行。 这些部分通常分别初始化和增加计数器; 但他们可以做任何事情。

第二部分是在每次执行开始时执行的testing。 如果testing产生false ,则循环被中止。 这就是它的全部。

循环的C风格由三个expression式组成:

 for (initializer; condition; counter) statement_or_statement_block; 
  • 初始化器在循环开始时运行一次。
  • 在每次迭代之前检查条件。 循环运行,只要它评估为真。
  • 计数器在每次迭代后运行一次。

这些部分中的每一个都可以是一个有效的expression方式,这就意味着可以更有创造性地使用它们。 任何你想事先做的事情都可以进入初始化器,任何你想要做的事情都可以进入条件或计数器,直到循环已经没有身体了。

为了实现这一点,逗号运算符非常方便。 它允许你将expression式链接在一起形成一个新的expression式。 大多数情况下,在for循环中这样使用,逗号运算符的其他含义(例如值赋值考虑因素)的作用很小。

即使你可以通过创造性地使用语法来做聪明的事情 – 我会保持清醒的,直到我find一个很好的理由这样做。 使用for循环播放代码高尔夫使代码更难阅读和理解(和维护)。

维基百科在for循环中也有一篇不错的文章 。

for循环中一切都是可选的。 我们可以初始化多个variables,我们可以检查多个条件,我们可以使用逗号运算符来迭代多个variables。

下面的for循环会带你进入一个无限循环。 检查条件要小心。

 for(;;) 

康拉德提到了我想重复的关键点:最右边expression的价值是整体expression的价值。

当Gnu编译器在for循环的“条件”部分中添加了两个testing时,它表示了这个警告

 warning: left-hand operand of comma expression has no effect 

我真正打算为“条件”是两个testing与“&&”之间。 根据康拉德的说法,只有逗号右侧的testing会影响条件。

for循环在特定的时间执行(;;)

for循环的syntex

对于(;;)

要么

for(initializer; condition; counter)

例如(rmv = 1; rmv <= 15; rmv ++)

执行到15次的块

首先初始化值,因为开始值

(例如)rmv = 1或rmv = 2

2.第二条语句是testing条件是真还是假,条件是真正的时间执行for循环和条件是假终止块,

例如,我= 5;我<= 10的条件是真实的

 i=10;i<10 the condition is false terminate for block, 

三是增量或减量

(例如)rmv ++或++ rmv