C 具有子作用域的函数的堆栈帧结构

C 具有子作用域的函数的堆栈帧结构,c,scope,stack-frame,storage-class-specifier,C,Scope,Stack Frame,Storage Class Specifier,下面是代码,我将其作为参考,以了解函数中存在的子作用域(或)伪作用域(只是{})如何影响堆栈框架的结构 #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

下面是代码,我将其作为参考,以了解函数中存在的子作用域(或)伪作用域(只是
{}
)如何影响堆栈框架的结构

#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
    中声明/定义的
    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(int i=0;i<10;i++)…
。该变量
i
将仅在for的主体内可见,您也可以通过定义另一个
i

局部变量来隐藏外部变量
main\u范围

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\u作用域创建了一个堆栈框架,但一旦程序退出该内部作用域,它就会被释放。

您是否检查了编译器选项?也许这个行为是可配置的;int main_scope=1
抛出一个错误,然后
int main\u scope=0;{int main_scope=1;}
也应该抛出一个错误,不是吗?虽然
{}
中的定义试图初始化一个新变量,但它应该与堆栈框架中的现有变量
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.*/
    } 
}