Almost every language has some method for passing parameters to functions and procedures. These mechanisms have evolved over times, and there are a number of important differences.
What you should know: The two most common methods for parameter passing in modern imperative languages are call by value and call by reference. Call by name is primarily of historical interest, but is closely related to the way that parameters are handled when macros are expanded, and has the same semantics as lazy evaluation in functional languages. Languages with input/output parameters support call by value-result which differs subtly from call by reference
Techniques used for argument passing in traditional imperative languages:
When talking about parameters, the formal parameters are the parameters associated with the function, and the actual parameters are the parameters that are used to call the function.
Call by value, by result, by value-result, are special cases of call by copy, where values are copied into and out of the procedure parameters.
call by value: copy going into the procedure. This is the mechanism used by both C and Java. Note that this mechanism is used for passing objects, where a reference to the objected is passed by value.
call by result: copy going out of the procedure, the formal parameters are copied back into the actual parameters. (Note that this only makes sense if the actual parameter is a variable, or has a l-value, such as an array element.)
call by value result: copy going in, and again going out
call by reference: The actual parameters and formal parameters are identified. The natural mechanism for this is to pass a pointer to the actual parameter, and indirect through the pointer
call by name: re-evaluate the actual parameter on every use. For actual parameters that are simple variables, this is the same as call by reference. For actual parameters that are expressions, the expression is re-evaluated on each access. It should be a runtime error to assign into a formal parameter passed by name, if the actual parameter is an expression. Implementation: use anonymous function ("thunk") for call by name expressions
Call by value is particularly efficient for small pieces of data (such integers), since they are trivial to copy, and since access to the formal parameter can be done efficiently.
Call by reference is particularly efficient for large pieces of data (such as large arrays), since they don't need to be copied. Call by reference also allows a procedure to manipulate the values of variables of the caller, such as in a swap routine.
Fortran uses call by reference, early versions of FORTRAN allowed constants to change their values, since they were also passed by reference!
Algol 60 has call by name, call by value
Ada uses different designations:
INis the same as call by value,
OUTis the same as call by result, and
IN OUTis the same as call by value result. In addition,
INparameters are local constants -- you can't assign into them.
C generally uses call-by-value, although there are inconsistencies in the language. In particular, compare how structures are passed, and how arrays are passed. (It can be argued that arrays are passed by reference.)
An important related concept: aliasing. Two variables are aliased if they refer to the same storage location. A common way that aliasing can arise is using call by reference. A formal parameter can be aliased to a nonlocal variable, or two formal parameters can be aliased.
begin integer n; procedure p(k: integer); begin n := n+1; k := k+4; print(n); end; n := 0; p(n); print(n); end;Note that when using call by reference,
call by value: 1 1 call by value-result: 1 4 call by reference: 5 5
begin array a[1..10] of integer; integer n; procedure p(b: integer); begin print(b); n := n+1; print(b); b := b+5; end; a := 10; a := 20; a := 30; a := 40; n := 1; p(a[n+2]); new_line; print(a); end;
call by reference: 30 30 10 20 35 40 call by name: 30 40 10 20 30 45