据我所知,堆栈变量是使用堆栈帧指针的绝对偏移量存储的。但是,以后如何处理这些变量呢?考虑以下代码:
#include <iostream>
int main()
{
int a = 0;
int b = 1;
int c = 2;
std::cout << b << std::endl;
}
编译器如何知道在哪里可以找到b
?它是否将偏移量存储到堆栈帧指针?如果是,这些信息存储在哪里?这是否意味着int
需要存储超过4个字节?
堆栈变量的位置(相对于堆栈指针(是编译时常数。编译器总是知道自函数开始以来,它被推送到堆栈中的东西有多少,因此也知道它们中任何一个在堆栈帧中的相对位置。(除非您使用alloca
或VLA1。(
在x86上,这通常是通过相对于ebp
或esp
寄存器寻址来实现的;开始";以及";结束";堆栈帧的。偏移量本身不需要存储在任何地方,因为它们是作为寻址方案的一部分构建到指令中的。
请注意,局部变量并不总是存储在堆栈中
编译器可以自由地将它们放在任何它想要的地方,只要它的行为就好像是在堆栈上分配的一样
特别是,像整数这样的小对象可以在其整个生命周期内简单地保留在寄存器中(或者直到编译器被迫将它们溢出堆栈(,常量可以存储在只读存储器中,或者编译器认为合适的任何其他优化。
脚注1:在使用alloca或VLA的函数中,编译器将使用一个单独的寄存器(如x86-64中的RBP(作为";帧指针";即使在优化的构建中,也要相对于帧指针(而不是堆栈指针(寻址本地。命名C变量的数量在编译时是已知的,因此它们可以位于堆栈帧的顶部,从它们到帧指针的偏移量是恒定的。多个VLA只能作为指针来工作,就像通过alloca来分配空间一样。(这是一种典型的实施策略(。