Association of actual and formal parameters upon function call. Six relatively common methods are:
- macro expansion.
Simplest; actuals evaluated, r-values passed. Used e.g. in C, Pascal.
- Formal treated like function-local name; allocated in activation record (usually stack).
- Caller evaluates actuals, places r-values in
- Operations on formals by body of callee do not affect values of caller's actuals (e.g. swap(x, y) cannot be implemented with call-by-value).
Caller passes called procedure a pointer to storage location of each actual parameter. Optionally used in Pascal (var
parameters). Arrays are usually passed by reference.
- If an actual is a name or an expression with an l-value, then that l-value is passed
- If an actual has no l-value (e.g. a temporary expression such as a+b), then the expression is evaluated into a new location (e.g. on the stack), and its address is passed.
- Callee references to parameters become indirections through the passed pointers. swap(x, y) is trivial to implement with call-by-reference.
(or "copy-restore", "copy-in copy-out")
Hybrid of call-by-value and call-by-reference.
- Actuals are evaluated and r-values passed as in call-by-value, but each parameter's l-value (if any) is determined before call
- Upon return, latest r-values of the formals are copied to locations specified by previously-determined l-values, when they exist.
- I.e. parameters are "copied in" for use by called procedure, which operates on its formals directly rather than indirectly through pointers, and upon return, the updated values are "copied out" -- copied back to the corresponding parameters which have l-values. Basically an optimization of call-by-reference.
- Semantics can differ from call-by-reference if an actual has an alias.
Historically introduced by the "copy-rule" of Algol:
- Procedure treated as macro (macro-expansion, inline expansion): body substituted for call in caller, actual parameters literally substituted for the formals.
- Callee locals kept distinct from caller's names, e.g. via systematic renaming to generated guaranteed-unique names.
- Actual parameters are surrounded by parenthesis before substitution (if necessary to preserve their lexical boundaries)
- swap(x, y) cannot be written with call-by-name (A.C. Fleck 1976)
. [[need description here]]
(Based on discussion in RedDragonBook
, sec 7.5)
AnswerMe: Can some one please explain the differences between macro-expansion, call-by-name and call-by-thunk? From the list at the top I'd gather that call-by-name is different from macro-expansion, but the explanation below that mixes them. And one the first words on 'CallByName' is 'thunk', and the explanations given all sound alike.
Following coming from ParameterPassingModes?, which is being merged in:
How one passes parameters/arguments from an outer scope to another scope (a function, macro, etc.) is a key issue in language design, with far-reaching consequences. Several different types are in use. It is useful to distinguish semantics
. (Note that issues like VariableCapture?
are not handled here; only those values passed explicitly as parameters).
Implementation techniques: How languages actually implement parameter passing.
Semantic modes. For some languages, such as CeeLanguage
, the implementation and the semantics are equivalent; in C you always get CallByValue
, can simulate CallByReference
with pointers, etc. For other languages, "higher level" semantics that define the observable behavior of parameter passing are what is important; implementations have freedom to implement how they like.
Finally, one other important consideration is when arguments are evaluated.
See also AlternativesToPassByReference