0 · Recall Warm-up
Answer from memory first. Answers are in the Answer Vault at the end of this lesson.
- Under dynamic scoping, where does a procedure find a non-local name? from Lesson 5.3
- Where do ordinary local variables live? from Lesson 5.1
- In recursive descent, how are inherited attributes passed? from Lesson 3.2
1 · The Story
📖
Handing over the figures
Mrs. Shah asks the accountant to adjust two figures. Rhea can hand him the figures in four ways.
A photocopy: he scribbles on it, and the original is untouched. The original file: every change he makes is in the real file at once, and if both figures are the same file, his two changes hit the same page. A photocopy he must return at the end: he works on the copy, and when he leaves, Rhea copies his final numbers back into the originals, one after the other. A note with instructions such as “the figure on row i of the ledger”: he follows the instructions afresh every time he needs the figure, so if i changes meanwhile, he looks at a different row.
2 · Predict First
🤔
With i = 0 and a = {10, 20, 30}, the procedure p(x, y) { x = x + 1; y = y + 1; i = i + 1; } is called as p(i, a[i]). Which mode can change a[1]?
Write your guess down. The answer is in the vault.
3 · Core Concept
Call by value
The caller evaluates the actual parameter and copies the value into the formal parameter. Changes to the formal are invisible to the caller. C uses only call by value (pointers are passed by value too). Java passes primitive values and object references by value.
Call by reference
The caller passes the address (l-value) of the actual parameter, computed once at the call. Every use of the formal reads or writes the caller’s variable. If two formals refer to the same variable (aliasing), a write through one is seen through the other. C++ reference parameters, Pascal var parameters.
Call by value-result (copy-restore)
On entry, copy the actual’s value into the formal (like value). On return, copy the formal’s final value back to the actual’s location (computed at the call), left to right. It behaves like reference unless there is aliasing or the procedure also touches the actual through another name; then results can differ. Ada in out parameters.
Call by name
The formal is replaced by the actual expression itself, re-evaluated in the caller’s environment every time the formal is used (implemented with a small function called a thunk). If the expression depends on a variable that changes during the call, each use may refer to something different. Algol 60.
How to trace (method)
- Write the caller’s variables in a table.
- At the call: value and value-result make copies; reference binds the formal to the actual’s address; name binds the formal to the expression text.
- Execute the body, updating the right cells.
- At return: value-result copies back in parameter order.
Story → compiler term
| In the story | In the compiler |
|---|---|
| a photocopy | call by value |
| the original file | call by reference |
| both figures being the same file | aliasing |
| a photocopy copied back at the end | call by value-result (copy-restore) |
| instructions “row i of the ledger”, followed each time | call by name (thunk) |
4 · Visual
int i = 0; int a[3] = {10, 20, 30};
void p(int x, int y) { x = x + 1; y = y + 1; i = i + 1; }
main() { p(i, a[i]); print(i, a[0], a[1], a[2]); }
| Mode | Output |
|---|---|
| by value | 1 10 20 30 |
| by reference | 2 11 20 30 |
| by value-result | 1 11 20 30 |
| by name | 2 10 21 30 |
Each row computed by running the program with that parameter mode.
5 · Worked Examples
Example 1 Easy
Explain each output of the program above.
Solution
Value: x, y are copies; only i = i + 1 changes the caller: i = 1. Reference: x is i, y is a[0] (the address of a[i] taken when i = 0): i = 1, a[0] = 11, then i = 2. Value-result: copies 0 and 10 become 1 and 11; the body sets the global i = 1; on return i = 1 and a[0] = 11 are copied back. Name: x is i and y is the expression a[i]: i = 1, then y = y + 1 means a[1] = a[1] + 1 = 21, then i = 2. Rhea’s four ways of handing over the figures.
Example 2 Medium
Aliasing: what is printed?
int a = 1;
void q(int x, int y) { x = x + 10; y = y * 2; }
main() { q(a, a); print(a); }
Solution
| Mode | Output |
|---|---|
| by value | 1 |
| by reference | 22 |
| by value-result | 2 |
| by name | 22 |
By reference (and by name, since a is a plain variable), x and y are both a: a = 11, then a = 22. By value-result, x = 11 and y = 2 are copied back in order x then y, so the last copy wins: a = 2.
Example 3 GATE
What does each mode print?
int x = 3;
int f(int y) { x = x + 1; return y + x; }
main() { print(f(x)); print(x); }
Solution
| Mode | Output |
|---|---|
| by value | `7 |
| by reference | `8 |
| by value-result | `7 |
| by name | `8 |
Value: y = 3, x becomes 4, returns 3 + 4 = 7. Reference: y is x, which becomes 4: 4 + 4 = 8. Value-result: y = 3, global x becomes 4, returns 3 + 4 = 7; then y’s final value 3 is copied back into x: x = 3. Name: y re-evaluates x = 4: 8.
6 · Shortcuts
⚡
Same-variable actuals (aliasing): reference and name see every write immediately; value-result applies the copies back left to right (the last parameter wins). Valid when: calls like f(a, a).
⚡
Array-element actuals with a changing index: reference fixes the element at the call; name re-evaluates the index at each use. Valid when: calls like p(i, a[i]) where the body changes i.
7 · GATE Traps
⚠️
- Value-result copies back to the location computed at the call, in parameter order.
- Call by name re-evaluates the actual expression at every use, including indices.
- For a simple variable actual without other aliasing, reference and name behave the same.
- C is call by value only; passing a pointer is still by value.
- Value-result and reference differ only with aliasing or global access to the same variable.
8 · Memory Hook
🧠
Photocopy, original, copy-and-return, instructions. Value, reference, value-result, name.
9 · Connect the Dots
Parameters and locals live in stack records that vanish at return. Some languages need data that outlives the call that created it, and some cannot use a stack at all. The last lesson of the phase asks which language features need fixed storage, a stack, or a heap.
10 · Self-Test
GATE format. Try every question before opening the vault.
Q1MCQ2 marksSwap
With i = 1 and a = {3, 2, 0, 1}, swap(i, a[i]) uses void swap(int x, int y) { int t = x; x = y; y = t; }. Under call by name, the final values of i, a[0..3] are:
- (A) 1 3 2 0 1
- (B) 2 3 1 0 1
- (C) 2 3 2 1 1
- (D) 1 3 1 0 1
Q2MCQ1 markSwap
Same call under call by reference:
- (A) 1 3 2 0 1
- (B) 2 3 1 0 1
- (C) 2 3 2 1 1
- (D) 1 2 3 0 1
Q3NAT2 marksAliasing
For int a = 2; void f(int x, int y) { x = x + y; y = x * y; print(x, y); } … f(a, a); print(a);, what is the final a under call by value-result (copy back x first, then y)?
Numerical answer: ________
Q4NAT2 marksJensen
By name: what does sum(i, a[i]) return with a = {1, 2, 3, 4} and
int sum(int k, int e) { int s = 0; k = 0; while (k < 4) { s = s + e; k = k + 1; } return s; }
Numerical answer: ________
Q5MSQ1 markFacts
Which are true?
- (A) C passes all arguments by value.
- (B) Call by name is implemented with thunks.
- (C) Value-result never differs from reference.
- (D) Call by reference passes the address of the actual parameter.
11 · Rule Card
- Value: copy in; caller unaffected.
- Reference: pass address (fixed at the call); aliasing possible.
- Value-result: copy in, copy back on return to call-time locations, in order.
- Name: re-evaluate the actual expression at every use (thunk).
- Trace with a table of the caller’s cells.
12 · Concept Ledger
call by valuecall by referencealiasingcall by value-result (copy-restore)call by namethunkl-value / r-value
13 · Answer Vault
Answer Vault
Try the questions first. Open when you are ready to check.
Warm-up
- In the most recently called active procedure that declares it.
- In the call’s activation record on the stack.
- As parameters of the procedures (synthesized ones are return values).
Predict First
Call by name. y stands for the expression a[i]; after x = x + 1 makes i = 1, y = y + 1 updates a[1]. Outputs per mode are in Example 1.
Self-Test
Q1 Answer: (C)2 marks
t = i = 1; i = a[i] = a[1] = 2; a[i] = a[2] = t = 1. Computed: 2 3 2 1 1.
- (A) is wrong: That is call by value.
- (B) is wrong: That is call by reference (a[1] fixed at the call).
- (D) is wrong: i changes.
Re-read: Lesson 5.4 — Parameter passing: by value, by reference, by value-result, by name; output tracing
Q2 Answer: (B)1 mark
y is bound to a[1] at the call: i = 2, a[1] = 1. Computed: 2 3 1 0 1.
- (A) is wrong: Value.
- (C) is wrong: Name.
- (D) is wrong: No.
Re-read: Lesson 5.4 — Parameter passing: by value, by reference, by value-result, by name; output tracing
Q3 Answer: 82 marks
x = 2 + 2 = 4, y = 4 × 2 = 8; copy back x then y: a = 8.
Re-read: Lesson 5.4 — Parameter passing: by value, by reference, by value-result, by name; output tracing
Q4 Answer: 102 marks
k is i and e is a[i]: the loop adds a[0] + a[1] + a[2] + a[3] = 10. By value it would be 4 × a[0] = 4.
Re-read: Lesson 5.4 — Parameter passing: by value, by reference, by value-result, by name; output tracing
Q5 Answer: (A) (B) (D)1 mark
They differ when aliasing occurs.
Re-read: Lesson 5.4 — Parameter passing: by value, by reference, by value-result, by name; output tracing