在C中,是在一个循环中声明的变量,本地?

时间:2012-12-22 03:50:22

标签: c loops local-variables

    #include <stdio.h>

    int a;

    void myproc()
    {
        int a = 2;
        while (a == 2)
        {
            int a = 3;
            printf("a = %d\t", a);
            break;
        }
        printf("a = %d\t", a);
    }

    int main()
    {
        a = 1;
        myproc();
        printf("a = %d\t", a);
        return (0);
    }

我希望打印上面的代码:a = 3 a = 3 a = 1 但是,它打印:a = 3 a = 2 a = 1有人可以提供有效的解释吗?

6 个答案:

答案 0 :(得分:6)

是的,它们是本地自动变量,当你进入和退出给定的范围时,它们被推入并弹出堆栈,除非编译器决定进行某些优化(例如将它们存储在寄存器中等)但是对于给定的变量,访问它时使用该变量的最本地范围的版本。例如,在C89中,如果您决定在for循环声明中声明循环计数器,则以下通常会产生编译器错误:

for (int i=0; i < N; i++)
    for (int i=0; i < J; i++)
        printf("%d", i);

打印的i值始终是内部for循环中声明的i的值,因为这是i的本地范围最大的版本。

答案 1 :(得分:6)

以下是解释 - 请参阅下面的评论。

#include <stdio.h>

int a;

void myproc()
{
    int a = 2; // (1) a = 2
    while (a == 2) // true
    {
        int a = 3;  // (2) new scope, new a = 3
        printf("a = %d\t", a); // (X) prints 3 as it gets the 'nearest a' in the scope
        break;
    } // throws away a=3 from (2)
    printf("a = %d\t", a); // (Y) Uses (1) i.e. 2 and print it 
}

int main()
{
    a = 1;
    myproc();
    printf("a = %d\t", a); // (Z) Just prints 1 as the scope is not effected by myproc
    return (0);
}

所以这将打印(X)(Y)和(Z)

即。 3 2 1

答案 2 :(得分:3)

“在循环中”?

你问的问题与任何循环完全没有关系。您的代码与普通代码之间没有区别

int a;

void myproc()
{
    int a = 2;
    {
        int a = 3;
        printf("a = %d\t", a);
    }
    printf("a = %d\t", a);
}

每个嵌套块都有自己的变量。这里的所有都是它的。它与任何循环无关。

与循环真正相关的声明将是循环标题中的声明,如

    int a = 3;

    for (int a = 0; a < 10; ++a)
    {
      ...
    }

    printf("a = %d\n", a); // <- prints `3`

a标头中声明的for仍然是循环的本地。

答案 3 :(得分:2)

{}变量声明范围。当您在这些大括号之间声明变量时,它仅在那些大括号中可用。如果你有嵌套变量(比如在myproc中声明a = 2然后在循环a = 3内)那么声明closet到当前作用域的变量是引用的变量(在例子中,a = 3)。

由于您的print语句嵌套在{}中,因此只会打印最近声明的变量a,从而获得结果。

答案 4 :(得分:1)

每当你在循环中声明一个变量时,该变量在外部不可用(超出该变量的范围)。所以在你的代码中

 void myproc()
{
    int a = 2;
    while (a == 2)
    {
        int a = 3;// This is not accessable to outside while loop. 
        printf("a = %d\t", a);
        break;
    }
    printf("a = %d\t", a);
}

如果要打印3,3,1,请在循环中删除 int :)

答案 5 :(得分:1)

实际上,循环是一个非常方便的混淆器。

考虑while循环的测试。该测试在程序执行期间运行两次,并且第一次测试成功,因为它正在检查它的值为2.第二次运行时,测试失败,因为它正在测试a是不同的a,持有价值3!这非常令人惊讶。

鉴于我的同事的解释,a的三个声明仅存在于其封闭的“{”和“}”分隔范围内(或第一个范围内的世界范围)。如果这确实是真的,那么while(a == 2)测试应该永远传递,因为内部一个分配给值3的声明被'{'和'}'完全隐藏

int a = 1;         // world scope - a is 1
myproc() 
 {                 // New scope; can define names inside here
  int a = 2;       // Redefine a to be 2
  while ( a == 2 ) // We test whether a is 2
  {                // New scope; can define names inside here 
    int a = 3;     // Redefine a to be 3  
  }                // end of scope, the a = 3 disappears; also branch back to top of loop
 }                 // end of myprog scope, so the a=2 disappears

理解这一点的方法是认识到while (test) { statements; }实际上实现为:

if ( test ) {      // T1
   L1: {
      statements;
      if ( test )  // T2 
          goto L1;
   }
} 

所以实际上,测试语句被复制,第一个'T1'在'{'和'}'之外的范围内执行,并获得a为2,并且通过;第二个'T2'在'{'和'}'的范围内执行,得到a为3,测试失败。

鉴于您的语句,第二个测试使用其本地作用域定义a为3,因此循环在一次通过后退出。