C中有什么完整的“for”循环语法(以及其他的兼容的情况)?
阅读其他人的代码时,我看到了一些非常奇怪for
循环。 我一直在尝试在C
为for
循环search完整的语法解释,但是这非常困难,因为单词“ for
”出现在不相关的句子中,使得search几乎不可能对Google有效。
这个问题出现在我的脑海,读了这个线程 ,让我很好奇。
在这里:
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语法是:
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; }
for循环的两个额外的细节没有被简化为上面的while循环:
- 如果条件被省略,它总是
true
(导致无限循环,除非break
,goto
,或者别的什么东西打断循环)。 -
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