【问题标题】:How does a compiler implement pass by value and pass by reference?编译器如何实现按值传递和按引用传递?
【发布时间】:2011-11-19 23:49:20
【问题描述】:

我想知道您是否可以帮助我了解编译器需要进行的按值传递和按引用传递背后的想法,涉及的步骤是什么?如果您能帮我解决这个问题,我会非常有帮助,因为我正在开发一个小型编译器项目。

【问题讨论】:

  • 这是一个非常广泛的、非具体的问题。像the dragon book 这样的东西可能是一个更好的起点......

标签: compiler-construction compilation pass-by-reference pass-by-value


【解决方案1】:

按值传递是最基本的传递形式。最终一切都是通过值传递来实现的。

如果您要问的是当调用函数并按值传递参数时实际发生了什么,这会因平台而异。每个平台都有自己的“调用约定”。大多数情况下,前几个参数存储在处理器寄存器中。任何剩余的参数都将存储在被调用函数的堆栈帧中的预定义位置,类似于局部变量。 (局部变量如何存储在堆栈帧中由编译器在编译时决定。)所以当一个函数被调用时,任何需要存储在堆栈中的参数都被复制到那里;并且任何需要存储在寄存器中的参数都在那里加载。然后将控制权传递给函数。

对于传递引用,如果一种语言有指针,传递引用可以通过按值传递指针来完成。编译器可以有一个预处理步骤,通过以下翻译“消除”引用传递:

  • 对于每个通过引用传递的函数参数,它会将其更改为指向按值传递的类型的指针(例如void func(int &foo) -> void func(int *foo)
  • 对于在该函数中每次使用该传递引用参数,将其更改为显式指针取消引用(例如foo -> *foo)(如果再次通过引用传递,则不要'不要取消引用它)
  • 每次调用该函数时,无论传递给按引用传递变量的什么,都明确地获取它的地址(例如func(bar) -> func(&bar)

【讨论】:

    【解决方案2】:

    这完全取决于编译器如何处理变量(可以称为“环境”)。

    当变量被转换为内存引用时(例如在 C 编译器中),传递引用可以通过在后台使用指针来实现,编译器生成必要的代码来取消引用指针。 Pass-by-value 是通过复制数据,然后引用副本来处理的。

    如果编译器使用符号表(解释器比编译器更典型),则可以通过将现有符号表条目复制到新变量的新条目来完成按值传递,而按引用传递只会使用现有的条目。

    其他环境需要其他方法。

    【讨论】:

      猜你喜欢
      • 2014-08-23
      • 2015-05-23
      • 1970-01-01
      • 2012-07-29
      • 2014-04-04
      • 1970-01-01
      • 2012-01-16
      • 2012-10-14
      • 1970-01-01
      相关资源
      最近更新 更多