在这个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?
答案 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 source或this source了解详情。