7
    #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 有人可以提供有效的解释吗?

4

6 回答 6

6

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

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

print 的值i将始终是i内部 for 循环中声明的值,因为这是i.

于 2012-12-22T03:54:42.333 回答
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

于 2012-12-22T03:59:07.487 回答
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内容仍然是循环的本地内容。

于 2012-12-22T04:16:32.417 回答
2

{ } 变量声明范围。当您在这些大括号之间声明一个变量时,它仅在这些大括号中可用。如果您有嵌套变量(例如在myproc您声明 a = 2 然后在循环内 a=3),则声明为最接近当前范围的变量是引用的变量(在示例中,a = 3)。

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

于 2012-12-22T03:58:05.317 回答
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 在 while 循环中删除int :)

于 2012-12-22T04:09:11.217 回答
1

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

考虑 while 循环的测试。这个测试在程序执行过程中运行了两次,第一次测试成功,因为它正在检查的 a 的值为 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'在'{'和'}'之外的范围内执行,并获得为2的a,并通过;第二个 'T2' 在 '{' 和 '}' 的范围内执行并获得为 3 的 a 并且测试失败。

给定您的语句,第二个测试使用其本地范围的 a 定义,即 3,因此循环在一次通过后退出。

于 2012-12-22T05:05:06.593 回答