Reference parameters

An alternative to using a return statement getting back values from functions is to pass parameters by reference. We have seen that arrays are always passed in this way.

A parameter which is passed by value results in its value being copied into a local (automatic) variable within the called function's block at the point of call. Like all automatic variables this is lost at the end of the function's execution and any changes made to its value within the code of the function are also lost.

Parameters which are passed by reference, however, can be thought of as having their address passed to the called function and so the called function can use this to change the contents of the variable in the calling function. (It clearly doesn't make much sense to try to alter the contents of a constant!)

Arrays are always passed in this way and any reference to them inside the called function is assumed to be an indirect one through the passed address to the original array in the calling function. No special syntax is needed to make this happen.

Other variables, including structs in ANSI C, are passed by value, unless you use some special symbols to force their passing by reference.

We have already seen that scanf requires its parameters to be passed in this way and that we have to use an ampersand (&) in front of the parameter name. The ampersand tells the compiler to pass over the memory address of the variable, not its value.

In the header of the function declaration you must write the description of the parameter as its type followed by an asterix (*) followed by its name. The asterix tells the compiler that a reference or pointer is being passed, not a value of the appropriate type. It needs to know this since the space taken up by a reference address may be different from the space taken up by the value it refers to.

Within the called function, when you want to access the value of a parameter passed by reference you must write the identifier of the parameter preceded by an asterix. If you forget the asterix, the value of the address is used. You will probably get a compiler warning message as well.

    void larger2(int * val1, int val2)
    {
        if (*val1>val2) *val1=val2;
    }
To see the effect of this, consider the output of the following program:
#include <stdio.h>

    void larger2(int * val1, int val2) {
        if (*val1<val2) *val1=val2;
    }

    void print2(int val1, int val2) {
        (void) printf("%d %d\n", val1, val2);
    }

    int larger1(int val1, int val2) {
        if (val1>val2) val1 = val2;
        return val1;
    }

    void main() {
        int I1, I2, I3;

        I1 = 4;
        I2 = 5;

        I3 = larger1(I1, I2);
        print2(I1,I2);

        larger2(&I1,I2);
        print2(I1,I2);
    }
Plain text version to compile.

The first print call outputs the unchanged values of I1 and I2, since the assignment to parameter val1 inside larger1 has not changed these variables. The second call will print out

5 5
since I1 was changed inside larger2 after being passed by reference.

Exercises on this section.


Next - Pointer variables.

Back to Contents page.