Compiler Design
Runtime Environment & Activation Records / Parameter Passing Mechanisms
Parameter Passing Mechanisms
Different programming languages employ different semantics for communicating values between callers and callee procedures.
The caller evaluates the actual parameters and passes a **copy** of the resulting values. The callee allocates a fresh memory slot inside its activation record to store this copy. Modifying the formal parameters inside the function changes only the local copy, leaving the caller's variables completely unaffected.
void increment(int x) {
x = x + 1; // modifies the local copy only
}
int main() {
int a = 10;
increment(a); // passes copy of 10
printf("%d", a); // prints 10 (UNCHANGED!)
}Used in: C (default), Java (primitives), Python.
The caller passes the **address (L-value)** of the actual variable. The formal parameter inside the callee becomes an **alias** (another name) referencing the exact same memory cell as the caller's variable. Any modification immediately updates the caller's variable.
void increment(int &x) { // x is a reference
x = x + 1; // modifies caller's variable
}
int main() {
int a = 10;
increment(a); // passes address of a
printf("%d", a); // prints 11 (CHANGED!)
}Used in: C++ (& parameters), Pascal (VAR parameters), C# (ref keyword).
A hybrid approach operating in three phases:
- Copy-In: At the start of the call, the actual parameter's value is copied into local variables.
- Execution: The procedure performs computations on the local copies.
- Copy-Out: At function return, the final values of the local copies are written back into the caller's original variables.
Used in: Ada (IN OUT parameters), some Fortran dialects.
The actual parameter expression is **textually substituted** for the formal parameter throughout the callee. The expression is re-evaluated every single time the formal parameter is accessed.
It is implemented using **thunks** — parameterless closures that freeze the expression and its scope context, passing it to the callee.
Used in: ALGOL 60. (Haskell's lazy evaluation is conceptually similar).
Summary Comparison Table
| Mechanism | What is Passed | Caller's Variable Affected? | Primary Advantage |
|---|---|---|---|
| Call by Value | Copy of value | Never | Safe: Caller's data is protected. |
| Call by Reference | Address of variable | Always (immediately) | Efficient: No copying overhead for objects. |
| Call by Value-Result | Value (copied both ways) | On return only | Excellent for remote procedure calls (RPC). |
| Call by Name | Unevaluated expression (Thunk) | Possible (depends on expression) | Evaluates only if parameter is used. |