c++ - 为什么编译器在编译时不知道局部变量的地址?

标签 c++ c variables memory-management

下面的语句是什么意思?

Local and dynamically allocated variables have addresses that are not known by the compiler when the source file is compiled

我以前认为局部变量是在编译时分配的地址,但这个地址可以在它离开范围时发生变化,然后在函数调用期间再次进入范围。但是上面的语句说编译器不知道局部变量的地址 那么局部变量是怎么分配的呢?为什么编译时可以知道全局变量的地址??

此外,您能否提供一个很好的链接来阅读如何分配局部变量和其他变量?

提前致谢!

最佳答案

上面的引述是正确的——编译器通常在编译时不知道局部变量的地址。也就是说,编译器可能知道局部变量所在的堆栈帧基址的偏移量,但根据调用堆栈的深度,这可能会在运行时转换为不同的地址。作为一个例子,考虑这个递归代码(顺便说一下,它绝不是好的代码!):

int Factorial(int num) {
    int result;
    if (num == 0)
        result = 1;
    else
        result = num * Factorial(num - 1);

    return result;
}

根据参数 num,此代码可能最终会进行多次递归调用,因此内存中将有多个 result 拷贝,每个拷贝包含不同的值。因此,编译器无法知道它们都将去哪里。但是,result 的每个实例可能会从包含每个 Factorial 调用的堆栈帧的底部偏移相同的量,尽管理论上编译器可能会做其他事情,比如优化这段代码使得只有一份 result 的拷贝。

通常,编译器通过维护栈帧模型并跟踪栈帧中下一个空闲位置的位置来分配局部变量。这样,局部变量可以相对于堆栈帧的开始分配,并且当函数被调用时,可以使用相对地址,结合堆栈地址,在特定堆栈帧中查找该变量的位置.

另一方面,全局变量可以在编译时知道它们的地址。它们与本地变量的主要区别在于程序中始终存在一个全局变量的拷贝。根据执行情况,局部变量可能存在 0 次或多次。由于存在一个唯一的全局拷贝,编译器可以为它硬编码一个地址。

至于进一步阅读,如果您想相当深入地了解编译器如何布置变量,您可能需要阅读 Compilers: Principles, Techniques, and Tools, Second Edition 的拷贝 作者:Aho、Lam、Sethi 和 Ullman。尽管本书的大部分内容都涉及其他编译器构造技术,但本书的很大一部分专门用于实现代码生成和可用于改进生成的代码的优化。

希望这对您有所帮助!

关于c++ - 为什么编译器在编译时不知道局部变量的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9187202/

相关文章:

c - 为什么在使用赋值运算符时,在 else 部分的 if-else 中需要简写左值?

无法将 arg 从 char 转换为 c 中的 const char

variables - '作为变量的符号值为 void :' when using parameter on defun inside lambda

c++ - 非阻塞套接字上的 read() 没有选择低延迟

c++ - `std::nullptr_t` 类型的用途是什么?

c++ - 在 C++ 中捕获未实现的纯虚拟

c - 未找到源 chkstk.asm

c - 函数静态变量的初始化

c++ - 如何在函数内部访问 Mat 类型参数的变量名

c++ - boost::spirit 可选解析为融合适应结构