【问题标题】:How are variables with the same name typically resolved?具有相同名称的变量通常如何解析?
【发布时间】:2012-02-12 14:00:44
【问题描述】:

假设这是我的程序在特定点的调用堆栈:

|    b = 2       |
|    c = 3       | <- function f2
| return address |
| function args  |
|     ...        |
|    c = 10      | <- function f1
|     ...        |

f1() 呼叫f2()

当变量 c 被引用时,它是如何解决的? 堆栈是线性自上而下地查找范围内名为 c 的第一个变量,还是有其他机制需要更有效地处理这个?

如果每次都查找栈,引用一个不存在的变量d会不会是个开销,因为会一直查找栈,发现范围内没有这个变量?

【问题讨论】:

  • 堆栈没有被“搜索”,编译器知道有多少变量,所以函数最终知道第 5 个局部变量距离堆栈指针 48 个字节。
  • “想多了”。不要将语言实现混淆。该语言精确地指定了您的代码的行为方式,并且它将这样做。
  • 当你的代码被编译时,任何变量名的使用都会被替换为相对于当前栈帧指针的地址。无需搜索。
  • +1 @KerrekSB 无需考虑堆栈,范围规则规定(1)在编译时知道使用哪个变量,(2)未定义的变量是编译时错误。这也适用于堆栈方面的每个答案/评论!

标签: gcc compiler-construction scope runtime


【解决方案1】:

在 C++ 中,在运行时变量没有名称。变量名只是为了方便程序员。变量在代码中有作用域,在堆栈中没有作用域。

因此在运行时不会搜索堆栈。在编译过程中,变量名被转换为内存地址。

【讨论】:

  • 如果内存只在运行时分配,内存地址怎么在编译时可用?
  • 我看不出我的回答与您的后续问题之间的联系,尽管它本身很有趣。
【解决方案2】:

引用由范围解析,基于变量的定义位置,而不是分配的位置。由于在您的示例中您没有显示任何定义,因此无法说。

在基于 C 的语言中没有嵌套过程(忽略其中一些“thunk”问题),因此堆栈本身不会被搜索。但是,您可以在单个过程中使用{} 字符嵌套静态范围,然后最内层范围(相对于引用点)“获胜”。否则,它是过程范围、类范围,然后是静态/全局范围。

【讨论】:

    【解决方案3】:

    (C 或 C++)编译器具有组织每个调用帧的艰巨任务。

    当在源代码中发出与局部​​变量相关的机器代码时,它会将局部变量的访问和修改转换为合适的指令(通常使用堆栈或帧指针作为一些基础)。

    调用帧中的给定位置可以(并且通常在编译器优化时)用于多种目的。

    一些局部变量在调用框架中没有对应部分:它们只存在于寄存器中。其他人有时会溢出。一个好的register allocator努力避免溢出。

    调用帧布局、寄存器分配、指令调度是优化编译器的困难任务。

    如果您好奇并且对您的 x86 处理器指令集有所了解,您可以尝试编写一个小型 C++ 文件 tiny.cc 并使用 g++ -Wall -fverbose-asm -O -S tiny.cc 编译它,然后查看生成的 tiny.s ,例如像 geditemacs 这样的编辑器或像 less 这样的寻呼机。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-14
      • 2020-10-27
      • 1970-01-01
      • 1970-01-01
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 2016-03-23
      相关资源
      最近更新 更多