C语言中块语句内定义的变量的生命周期

时间:2012-10-17 12:47:26

标签: block lifetime

在这个C代码片段中:

void func(void)
{
   int x=10;
   if (x>2)
   {
      int y=2;
      //block statement
      {
         int m=12;
      }
   }
   else
   {
      int z=5;
   }  
}

何时从func堆栈帧分配和释放x,y,z和m?

3 个答案:

答案 0 :(得分:2)

实际的分配取决于你的编译器,但是许多编译器在函数开头的堆栈上分配空间,并在函数返回之前释放它。请注意,这与变量实际可访问时是分开的,直到它们被定义的块结束。

在您的示例中,启用优化后,编译器可能不会为您的变量在堆栈上分配任何空间而只返回,因为它可以在编译时确定该函数实际上没有任何影响。 / p>

答案 1 :(得分:0)

根据C ++规则,您应该认为每个局部变量在其块的末尾都被销毁。这是调用析构函数的时间。但是,编译器可能决定在函数的开头/结尾一起分配/释放所有局部变量,这就是VC ++编译器所做的:

void func(void)
{
001413B0  push        ebp  
001413B1  mov         ebp,esp  
001413B3  sub         esp,0F0h  
001413B9  push        ebx  
001413BA  push        esi  
001413BB  push        edi  
001413BC  lea         edi,[ebp-0F0h]  
001413C2  mov         ecx,3Ch  
001413C7  mov         eax,0CCCCCCCCh  
001413CC  rep stos    dword ptr es:[edi]  
    int x=10;
001413CE  mov         dword ptr [x],0Ah  

    if (x>2)
001413D5  cmp         dword ptr [x],2  
001413D9  jle         func+3Bh (1413EBh)  
    {
        int y=2;
001413DB  mov         dword ptr [y],2  
        //block statement
        {
            int m=12;
001413E2  mov         dword ptr [m],0Ch  
        }
    }
    else
001413E9  jmp         func+42h (1413F2h)  
    {
        int z=5;
001413EB  mov         dword ptr [z],5  
    }  
}

但这些是实现细节,编译器可以通过另一种方式自由调整堆栈指针。

因此,没有定义实际的堆栈指针调整,但构造函数/析构函数调用完全根据函数内部块完成。当然,你不能在其块之外使用变量 - 这不是编译的。虽然此时可能会分配堆栈空间。

答案 2 :(得分:0)

如果是自动变量(默认情况下在代码块中声明的变量是自动的),则在进入块时自动分配内存,并在退出块时自动释放(如果您使用带有gcc的c)。您可以查看this sourcethis source了解详情。