编译器如何实现按值传递并通过引用传递?

时间:2011-11-19 23:49:20

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

我想知道您是否可以帮助我了解传递值背后的想法并通过引用传递编译器需要做的,涉及的步骤是什么?如果你能帮我解决这个问题,我会非常乐于助人,因为我正在开发一个迷你编译器项目。

2 个答案:

答案 0 :(得分:3)

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

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

对于pass-by-reference,如果一个语言有指针,可以通过按值传递指针来完成按引用传递。编译器可以只进行预处理步骤,通过进行以下转换来“消除”通过引用传递:

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

答案 1 :(得分:2)

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

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

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

其他环境需要其他方法。