1 while ( condition )
2 statement;
3 more_code();
在上面的代码sn-p中,只要condition是true,statement就可以重复执行。在 while 循环的每次迭代中,condition 被评估为 true 或 false。如果是false,while 循环结束并继续执行超出它的范围(在这种情况下,第 4 行带有more_code()。
我们通常习惯于用大括号{ 和} 将我们希望在循环中执行的部分代码括起来,但这不是强制性的。如果我们不这样做,循环代码将由单个语句组成,即紧跟在while 部分之后的语句。
实际上可以说,在更常见的情况下,我们将 while 与括在 代码块 内的大括号组合在一起,可以解释为提供此代码块就位 em> 单个语句,大括号提供了应该处理该块的信息(通过编译器分析它与前后代码的关系)就好像它是单个语句。
但是,由于提供单个语句而不是通常的代码块是完全有效的,因此值得了解的是存在一个空的有效语句。我们通过键入一个分号而不在它前面加上导致任何事情的代码来得到一个空语句。所以以下是完全有效的:
1 code;
2 ; // empty statement
3 ; // another empty statement
实际上是这样的:
1 code;; // a "code" statement followed by empty statement in the same line
while( condition ) 部分不以分号结尾,因此如果它应该控制一些实际代码(condition 除外),则不应在其后跟分号。如果它后面紧跟一个分号,则该分号将构成(并被编译器解释)一个空语句,因此循环代码将为空。如果这是无意的,那么我们想要循环的代码,无论是代码块还是语句,都不会循环,而是在循环结束之后(和 if)执行一次。
1 int a = 0;
2 while ( a < 3 ) ; // Next line is not part of loop - only the empty statement this semicolon creates is. This loop is infinite, or in other words it will never end.
3 a++; // This won't be executed even once.
4 printf("This never happens.");
(值得意识到的是,在 C 语言中,行只对我们人类很重要。行和缩进如果代表程序员的意图,则当他未能按照自己的意愿编写代码时,它们可能会产生误导.)
因此,问题的两个 sn-ps 中发生的情况是,我们会不断评估 condition,直到它产生 false。要了解发生了什么,我们需要检查逗号运算符的工作方式。
(注意,虽然逗号作为字符可以在 C 中的不同位置以完全不同的含义使用 - 我可以想到函数声明、定义和调用 - 在这种情况下,逗号字符是条件的一部分,因此它充当运算符 - 类似于 + 或 % 运算符。)
expression1 , expression2
逗号运算符导致先计算expression1,然后计算expression2,并返回expression2的值。
在每次评估条件时,我们将评估两个表达式(在这种情况下都是操作数,i++ 和 i<=8),然后将右侧的值视为逗号操作数本身的结果,因此为我们条件的价值。因此,只要正确的操作数解析为 true,循环就会不断重复。
虽然我们通常使用条件来控制循环的执行,但在这种情况下,condition 可能会产生“副作用”(有意或无意)。在我们的例子中,变量i 受到condition 的每次评估的影响:它增加一。
我们的示例仅在condition 的操作数顺序上有所不同,因此请注意真正控制循环执行的正确操作数。
让我们先来看看第二个例子。在这种情况下,我们有条件i++, i<=8。这意味着在每次评估时我们首先增加i,然后检查它是否小于或等于8。所以在第一次评估条件时,我们将i从0增加到1并得出1i 变为9 时,这样构造的循环将中断,即。第 9 次迭代。
现在对于第一个例子,条件是i<=8, ++i。由于比较没有副作用,也就是说,我们可以以任何顺序执行任意数量的比较,如果这是我们唯一做的事情,也就是说,如果我们没有以依赖于比较结果的方式或顺序执行任何其他操作,这些比较绝对没有任何作用。在我们的例子中,我们评估i<=8,其评估结果为true 或false,但我们没有使用这个结果,只是继续评估正确的操作数。所以左操作数绝对无关紧要。另一方面,右操作数有副作用,它的值变成了整个条件的值。在每次循环迭代之前,我们检查 i++ 的计算结果是 true 还是 false。
i++ 是后自增的一元运算符。它返回 i 的值 然后 将其加一(i++ 和 ++i 之间的区别是微妙的,但在这种情况下至关重要)。所以我们首先检查i是true还是false,然后i加一。
在 C 中没有 boolean 类型。如果整数具有非零值,则将其视为true。
所以在第一次评估 i++ 时,我们得到 0,即 false。这意味着循环被打破,甚至没有一次迭代。但是,它不会破坏对i++ 的评估,这会导致i 在我们完成循环之前增加一并且执行超出它。所以一旦我们完成了 while 循环,i 已经是 1。
如果我们想要非常精确地理解,那么我们获取评估整个条件的结果的部分会按时间顺序发生,在我们完成执行此评估所涉及的任何代码之后。所以我们首先记住i 在我们到达i++ 部分时为0,然后我们将i 加1,然后我们完成了condition 的执行,所以我们为代码提供值0决定我们是否应该进行另一次(在这种情况下是首先)迭代或跳过循环部分并继续前进。这就是为什么即使循环将结束的事实已经确定,但条件内的所有事情都会实际发生的确切原因:它已确定,但直到condition 完成执行才对其进行检查和操作。