这在编译器内部非常依赖于编译器,但从逻辑上讲,变量声明时就已经分配了存储空间。
考虑下面这个简单的C++示例:
int addtwo(int a)
{
int x = 2;
return a + x;
}
当GCC编译时,会生成以下代码(
;我的注释):
.file "junk.c++"
.text
.globl _Z6addtwoi
.type _Z6addtwoi, @function
_Z6addtwoi:
.LFB2:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $16, %esp
.LCFI2:
movl $2, -4(%ebp)
movl -4(%ebp), %edx
movl 8(%ebp), %eax
addl %edx, %eax
leave
ret
.LFE2:
.size _Z6addtwoi, .-_Z6addtwoi
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
_Z6addtwoi和.LCFI2之间的所有内容都是样板代码,用于设置堆栈帧(安全地存储先前函数的变量等)。最后一个“subl $16, %esp”是分配本地变量x的操作。
.LCFI2是您键入的第一部分实际执行代码。“movl $2,-4(% ebp)”将值2放入变量中。现在已经分配并初始化了空间。然后它将该值加载到寄存器EDX中,并将参数(在“8(% ebp)”中找到)移动到另一个寄存器EAX中。然后将两者相加,将结果留在EAX中。这是您实际键入的任何代码的结尾。其余部分仍然只是样板。由于GCC要求整数返回在EAX中,因此无需进行任何工作即可获得返回值。 "leave"指令撤销堆栈帧,“ret”指令将控制返回给调用者。
TL;DR摘要:您可以认为您的空间已随着块(配对{})的第一行可执行代码而被分配。