以下是我用来理解函数中存在的子作用域(或)伪作用域(仅为{}
)如何影响堆栈框架结构的代码。
#include <stdio.h>
int main()
{
int main_scope=0; /*Scope and life time of the variable is throughout main*/
{
//From below two statements I assume that there
//is no seperate "stack frame" created for just
//braces {}.So we are free access (scope exists) and
//modify (lifetime exists) the variable "main_scope"
//anywhere within main
main_scope++;
printf("main_scope++:(%d)n",main_scope);
//I expected this statement to throw an error saying
//"Multiple definition for "main_scope".But it isn't????
int main_scope=2;
printf("Value of redefined main_scope:(%d)n",main_scope);
}
printf("Finally main_scope in %s:(%d)n",__FUNCTION__,main_scope);
return 0;
}
样本输出
main_scope++:(1)
Value of redefined main_scope:(2)
Finally main_scope in main:(1)
基于上述行为,我推测如下。
- 没有为作用域
{}
创建堆栈帧 - 通过这种方式,在
main
中声明/定义的auto
变量和子范围{}
内的变量共享相同的堆栈帧 - 因此,在
main
中声明/定义的变量可以在函数内的任何位置(甚至在子范围内)自由访问 - 另一方面,在子作用域中声明/定义的变量在块外失去了其作用域。但只要存在堆栈帧,它的寿命就有效
问题:如果以上几点是对的,那么当为同一变量给出多个定义时,为什么代码没有失败,一个在main
中,另一个在{}
中。
硬件堆栈在这里无关紧要。对于所有局部变量,它在函数入口只能增长一次,在函数出口只能收缩一次;或者,它可以在每次定义新的局部变量并在其封闭{}时销毁时增长和收缩。
相关的是变量的"可见性"。
int main_scope=0;
{
main_scope++;
printf("main_scope++:(%d)n",main_scope);
// the main_scope variable that was assigned 0 is the most recent
// visible declaration of main_scope.
int main_scope=2;
// now, the previous declaration of main_scope is obscured by the new one,
// and so, you're going to access the new one
printf("Value of redefined main_scope:(%d)n",main_scope);
}
printf("Finally main_scope in %s:(%d)n",__FUNCTION__,main_scope);
// the previous scope inside {} is left, so, main_scope is going to be
// the one, to which we assigned 0
在内部/子作用域中定义与外部/超级作用域同名的对象是完全合法的。后者将在{}范围内被遮挡。
仅作为参考,还有一些其他地方可以出现变量定义,例如在for(;;)
语句的第一个表达式中:for (int i = 0; i < 10; i++) ...
。该变量i
将仅在for的内部可见,您也可以通过定义另一个i
将其隐藏在那里。
局部变量隐藏外部变量main_scope
。
int main()
{
int i=1;
{
int i=2;
printf("%d", i);
/* Whenever you use i here, it's always the local one that's used.
The outer i is hidden by the local i. But the local i will be deallocated
once the scope exits.*/
}
}
在C中完全合法。(注意,这在C++中是非法的!)
在您的示例中,肯定会为内部main_scope
创建一个堆栈帧,但一旦程序超出该内部范围,它就会被释放。