#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有人可以提供有效的解释吗?
答案 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,因此循环在一次通过后退出。