for循环中的循环变量何时更新?

时间:2015-10-31 22:41:29

标签: c for-loop

在开始for循环之前,循环变量是否得到更新?或者在for循环的每次迭代结束时?

我尝试编写测试代码来自行解决,但我不确定它是否适合测试。

#include <stdio.h>

int main(void)
{
  int i;

  for (i = 0; i < 5; i++) // does i++ happen here
    {
      printf("%d\n", i); // or does it happen after this is executed?
    }

  return 0;
}

使用此while循环,可以清楚变量的更新位置:

#include <stdio.h>

int main(void)
{
  int j;

  j = 0;
  while (j < 5)
    {
      printf("%d\n", j);
      j++; // j updates here
    }

  return 0;
}

提前致谢。

7 个答案:

答案 0 :(得分:1)

根据标准 ISO / IEC 9899:2011信息技术 - 编程语言 - C§6.8.5.3/ 1 for语句 (Emphasis Mine)

  

声明

     

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

     

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

因此,增量发生在for循环的每次迭代结束时。

您还可以在以下示例中看到此信息。 for循环最有可能由编译器实现,如goto语句。请考虑以下代码:

int main(void) {
  int i;
  for (i = 0; i < 5; i++) {
  }
}

此代码生成的汇编代码为:

main:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    $0, -4(%rbp)
.L3:
    cmpl    $4, -4(%rbp)
    jg  .L2
    addl    $1, -4(%rbp)
    jmp .L3
.L2:
    movl    $0, %eax
    popq    %rbp
    ret

LIVE DEMO

如果您专注于.L3(即for循环),您会注意到该陈述

addl    $1, -4(%rbp)

是增量发生的地方(即++i)。在该命令之后,跳回.L3(即下一次迭代)。

答案 1 :(得分:1)

在循环体完成后,将评估表达式i++

功能上,形式的for循环

for (i = 0; i < 5; i++)
{
  printf("%d\n", i);
}

与;

等效
i = 0;
while (i < 5)
{
    {
         printf("%d\n", i);
    }
    i++;
}

答案 2 :(得分:1)

尽管我之前的回答是,我说的是废话,我建议你看看:postfix and prefix increment operator in a for loop

基本上上面的帖子归结为你的问题是增量发生在循环传递的结束处。

答案 3 :(得分:1)

expr1;
while (expr2) {
    code;
    expr3;
}

相当于

strlen

所以是的,增量发生在身体完成之后。以下是int strlen(char *s) { int i; for (i = 0; s[i]; ++i) ; return i; }

的实现
int strlen(char *s)
{
    int i;

    i = 0;
    while (s[i])
        ++i;

    return i;
}

与:

相同
lag

答案 4 :(得分:1)

与OP for / while示例的唯一区别在于breakcontinue和范围规则会发生什么。

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

表现得像

{
  clause-1;
  while (expression-2) {
    {
      statement;
      // Should the statement contain a `continue` or `break`, then flow jumps as indicated.
      // a `continue` goes to continue_label:
      // a `break` goes to break_label:
   }
    continue_label:
    expression-3;
  }
  break_label:
}

范围所需的额外外部{}clause-1应该int x = 1;

不一样
  int x = 1;
  while (expression-2) {

但是喜欢

{
  int x = 1;
  while (expression-2) {

范围也需要最里面的{}。检查以下代码的3 j s。

的输出顺序和地址
int main(void) {
  int j;
  printf("1 %p\n", (void*) &j);
  for (int j = 0; 
       printf("2 %p\n", (void*) &j), j < 3;
       j++, printf("4 %p\n", (void*) &j)) {
    int j;
    printf("3 %p\n", (void*) &j);
  }
  return 0;
}

1 0x28ac1c
2 0x28ac18
3 0x28ac14
4 0x28ac18
2 0x28ac18
3 0x28ac14
4 0x28ac18
2 0x28ac18
3 0x28ac14
4 0x28ac18
2 0x28ac18

答案 5 :(得分:0)

在for循环中,每次迭代后都会完成增量。
while循环更可控,你可以在任何你想要的地方做到这一点!

答案 6 :(得分:0)

i++发生在for循环体之后。根据{{​​3}},

 for (initialize; test; step)
   statement
     

for语句首先计算表达式initialize。然后呢   评估表达式测试。如果test为false,则循环结束   语句后恢复程序控制。否则,如果是测试   如果是,则执行语句。最后,评估步骤,并且   循环的下一次迭代从再次评估测试开始。