C编程-while循环中的逗号运算符[重复]

Posted

技术标签:

【中文标题】C编程-while循环中的逗号运算符[重复]【英文标题】:C Programming - comma operator within while loop [duplicate] 【发布时间】:2017-05-27 11:09:09 【问题描述】:

程序 1:

#include<stdio.h>
 int main()
 
     int i=0;
     while(i<=8,i++);
     printf("%d",i);
     return 0;
  

程序 2:

#include<stdio.h>
 int main()

  int i=0;
  while(i++,i<=8);
  printf("%d",i);
  return 0;

Prog 1 的输出为 1,Prog 2 的输出为 9。

有人能解释一下这里发生了什么吗?这两个代码有何不同?

【问题讨论】:

我认为这个问题不是重复的。当然,如果分别正确理解 while 循环语法和逗号运算符语法和功能,则无需外部帮助即可理解此问题。但是我认为仅仅因为知识会阻止这个问题就假设一个问题是不合适的是不对的。由混淆引起的问题也很有帮助,因为许多人可能会以完全相同的方式感到困惑,受益于对复杂概念及其关系的量身定制的解释。 【参考方案1】:

逗号运算符依次计算它的两个参数,丢弃结果,除了最后一个。最后计算的表达式决定了整个表达式的结果。

i&lt;=8,i++ - 这里表达式的值是i++ 的值,也就是i 在递增之前的值。它为 0,因此循环立即终止。

i++,i&lt;=8 - 这里表达式的值是 i&lt;=8 的值,只有当 i 增加到 9 时才为 0。

就个人而言:我认为第二种形式虽然在某种程度上类似于 for 循环,但对于代码的读者来说不如真正的 for 循环那么清楚。

【讨论】:

【参考方案2】:
1 while ( condition )
2    statement;
3 more_code();

在上面的代码sn-p中,只要conditiontruestatement就可以重复执行。在 while 循环的每次迭代中,condition 被评估为 truefalse。如果是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&lt;=8),然后将右侧的值视为逗号操作数本身的结果,因此为我们条件的价值。因此,只要正确的操作数解析为 true,循环就会不断重复。

虽然我们通常使用条件来控制循环的执行,但在这种情况下,condition 可能会产生“副作用”(有意或无意)。在我们的例子中,变量i 受到condition 的每次评估的影响:它增加一。

我们的示例仅在condition 的操作数顺序上有所不同,因此请注意真正控制循环执行的正确操作数。

让我们先来看看第二个例子。在这种情况下,我们有条件i++, i&lt;=8。这意味着在每次评估时我们首先增加i,然后检查它是否小于或等于8。所以在第一次评估条件时,我们将i从0增加到1并得出1i 变为9 时,这样构造的循环将中断,即。第 9 次迭代。

现在对于第一个例子,条件是i&lt;=8, ++i。由于比较没有副作用,也就是说,我们可以以任何顺序执行任意数量的比较,如果这是我们唯一做的事情,也就是说,如果我们没有以依赖于比较结果的方式或顺序执行任何其他操作,这些比较绝对没有任何作用。在我们的例子中,我们评估i&lt;=8,其评估结果为truefalse,但我们没有使用这个结果,只是继续评估正确的操作数。所以左操作数绝对无关紧要。另一方面,右操作数有副作用,它的值变成了整个条件的值。在每次循环迭代之前,我们检查 i++ 的计算结果是 true 还是 false

i++ 是后自增的一元运算符。它返回 i 的值 然后 将其加一(i++ 和 ++i 之间的区别是微妙的,但在这种情况下至关重要)。所以我们首先检查itrue还是false,然后i加一。

在 C 中没有 boolean 类型。如果整数具有非零值,则将其视为true

所以在第一次评估 i++ 时,我们得到 0,即 false。这意味着循环被打破,甚至没有一次迭代。但是,它不会破坏对i++ 的评估,这会导致i 在我们完成循环之前增加一并且执行超出它。所以一旦我们完成了 while 循环,i 已经是 1。

如果我们想要非常精确地理解,那么我们获取评估整个条件的结果的部分会按时间顺序发生,我们完成执行此评估所涉及的任何代码之后。所以我们首先记住i 在我们到达i++ 部分时为0,然后我们将i 加1,然后我们完成了condition 的执行,所以我们为代码提供值0决定我们是否应该进行另一次(在这种情况下是首先)迭代或跳过循环部分并继续前进。这就是为什么即使循环将结束的事实已经确定,但条件内的所有事情都会实际发生的确切原因:它已确定,但直到condition 完成执行才对其进行检查和操作。

【讨论】:

@bhass1 虽然您的编辑受到赞赏,但在这种特殊情况下,添加大括号会失去价值。大括号不是所讨论的 sn-p 的一部分,你明白我的意思吗?您可能知道,大括号不是强制性的,它们的缺失可能会让一些新程序员感到困惑,并且在这种情况下需要成为正确答案的一部分。【参考方案3】:

表达式分隔符, 强制从左到右求值,也是一个排序点

Prog 1:考虑i &lt;= 8, i++i &lt;= 8 被评估并丢弃,然后i++ 被评估。整个表达式具有未递增的值i。因为i 最初是0,所以while 循环在第一次迭代时终止。输出将是 i 的单个递增值,即 1。

Prog 2:评估i++ 并丢弃结果,然后使用i 值评估i &lt;= 8,因为, 是一个序列点时间>。所以while 循环一直运行,直到i &lt;= 8 不再是true,增量值为i。输出将是 9。

【讨论】:

以上是关于C编程-while循环中的逗号运算符[重复]的主要内容,如果未能解决你的问题,请参考以下文章

FOR循环中的逗号运算符,它是如何工作的?

c中的逗号运算符[重复]

用逗号运算符做 while ( , ) ,这可能吗?

如何提高循环效率

逗号运算符

while循环php中的最后一个元素[重复]