【问题标题】:Can we interchange the for loop parameters in C?我们可以互换 C 中的 for 循环参数吗?
【发布时间】:2020-07-07 15:21:24
【问题描述】:
#include <stdio.h>

int main(void) {
    char i=250;
    for(i<0;i++;i=0,printf("%d", i));
    return 0;
}

在这个程序中,输出为 0。据我了解,for 循环应该有第一个参数作为初始化,然后是条件,然后是增量。但是在这个问题中,初始化是最后发生的,并且代码仍然给出了有效的结果。谁能解释一下?

【问题讨论】:

  • 您的代码没有多大意义。初始化步骤 (i&lt;0) 是一个逻辑比较,其结果被丢弃。只要i 不为零,循环条件i++ 就会评估为真,并且如果您在增量步骤中将i 设置为零,那么它打印出零也就不足为奇了。
  • 标题的答案——不,你不能。
  • @EugeneSh.:显然你可以,因为有人已经这样做了。
  • @EricPostpischil 这个问题暗示“..没有后果”或“..没有改变行为”。但你当然可以挑剔。
  • @EugeneSh。我同意。这里很明显地暗示了“没有后果”。

标签: c for-loop syntax evaluation


【解决方案1】:

for 语句中的子句或表达式总是根据它们在for 语句中的位置(第一个、第二个或第三个)来解释。在这段代码中:

char i=250;
for(i<0;i++;i=0,printf("%d", i));
return 0;
  • i 设置为 250(如果 char 是无符号的)或 -6(如果 char 是有符号的,八位,并且典型的二进制补码包装用于从 250 到 char 的转换)。 (C 标准允许其他可能性,但它们是不寻常的,在此答案中未进一步讨论。)
  • 为了启动循环,初始子句i&lt;0 被计算。它的结果是无关紧要的,因为它被忽略了。
  • 要确定循环是否结束,会评估测试子句i++。根据上述,这会产生 250 或 -6,并且分别将 i 增加到 251 或 -5。在任何一种情况下,表达式的结果都不为零,因此循环继续。
  • 对循环体; 求值。由于这是一个空语句,因此没有任何作用。
  • 评估后迭代子句i=0,printf("%d", i)。这会将i 设置为0 并打印i,从而输出“0”。
  • 再次评估测试子句i++。由于 i 为零,因此生成 0,并分别将 i 递增到 1。由于表达式的结果为零,因此循环终止。
  • return 0; 被执行,导致程序以成功状态结束。

【讨论】:

    【解决方案2】:

    简短回答您的问题“我们可以在 C 中互换 for 循环参数吗?”是:

    如果不是为了让读者感到困惑,这段代码一定是写得不好。

    演练

    1. i 初始化为 250
    2. i&lt;0 因为初始化步骤被忽略了
    3. i++ 被执行,因为旧的i 不是0,循环继续
    4. 循环体中没有任何内容
    5. 设置i=0并将其值0打印出来
    6. 回到i++,注意到之前的i 值为零,所以循环停止

    【讨论】:

      【解决方案3】:

      其实for循环的工作方式如下:

      for (step 0; step 1; step 3) {
          step 2;
      }
      

      这里,步骤 0 只执行一次。然后 step 1 -> step 2 -> step 3 -> step 1 循环继续。

      for 循环的第一个参数应该是初始化,然后是条件,然后是增量。

      这更像是一种约定。并且以这种方式解释 for 循环非常有意义(特别是因为在步骤 1 中,程序执行语句并仅在返回 true 时继续执行步骤 2)。所以我们以这种方式利用for循环。

      【讨论】:

        【解决方案4】:

        "我们可以在 C 中互换 for 循环参数吗?"

        我们可以交换表达式本身(无论出于何种原因,例如作为实验,因为这样做通常没有意义),但我们不能更改语法(如何在某个地方评估表达式)。

        for 循环具有固定语法,通常遵循以下形式:

        for (initializations; condition; in-/decrements)
        

        你可以在任何你想使用的地方使用表达式,但它有完全不同的效果。

        例如,如果将初始化表达式放在第二个位置,它们将用作条件。

        如果您将增量/减量放在第二位,也是如此。然后它们也将被评估为条件。

        同样,如果您将用作条件的表达式放在第一位或第三位,则该表达式将不再用作条件。

        这就是 C 标准对这个主题所说的:

        6.8.5.3 for 语句

        1 声明

        for (clause-1; expression-2; expression-3) statement 
        

        的行为如下: 表达式 expression-2 是在每次执行循环体之前计算的控制表达式。每次执行循环体后,表达式 expression-3 被评估为 void 表达式。 Ifclause-1 是一个声明,它声明的任何标识符的范围是声明的其余部分和整个循环,包括其他两个表达式;它在控制表达式的第一次评估之前按照执行顺序到达。如果 Clause-1 是一个表达式,它在控制表达式的第一次计算之前被计算为一个 void 表达式。161)

        2 子句 1 和表达式 3 都可以省略。省略的表达式 2 被非零常量替换。

        来源:ISO/IEC 9899:2018 (C18),§6.8.5.3

        【讨论】:

          【解决方案5】:

          一个for循环for(init; cond; inc) { body }基本上是这样执行的:

          init;
          while(cond) {
              body;
              inc;
          }
          

          在某些情况下可以切换事物,但在一般情况下不是。

          【讨论】:

            猜你喜欢
            • 2010-10-20
            • 1970-01-01
            • 2021-06-13
            • 1970-01-01
            • 1970-01-01
            • 2020-08-04
            • 1970-01-01
            • 2021-05-15
            • 2019-11-12
            相关资源
            最近更新 更多