There are two ways in which a function can be called: (a) Call by Value and (b) Call by Reference. In this chapter, we will explain the mechanism of calling a function by reference.
Let us start this chapter with a brief overview on “pointers” and the “address operator (&)”. It is important that you learn these two concepts in order to fully understand the mechanism of Call by Reference.
The Address Operator (&) in C
In C language, a variable is a named memory location. When a variable declared, the compiler allocates a random location in the memory and internally identifies the location with the user-defined name.
To fetch the address at which the variable has been created, we use the address (&) operator.
Example
Take a look at the following example −
#include <stdio.h>intmain(){int x =10;printf("x: %d Address of x: %d", x,&x);}
Output
This will print the value of x and its address −
x: 10 Address of x: -1990957196
What is a Pointer in C?
A pointer is a variable that stores the address of another variable. To declare a pointer variable, its name is prefixed with the * symbol. The type of the pointer variable and its host variable must be same.
The address is assigned with the & operator. The dereference operator (*) is used with the pointer. It fetches the value of a variable whose address is assigned to the pointer.
Example
The following example demonstrates how referening and dereferencing work in C −
#include <stdio.h>intmain(){int x =10;int*y =&x;printf("x: %d Address of x: %d\n", x,&x);printf("Address of y: %d \n",&y);printf("Value at address in y: %d\n",*y);}
Output
Run the code and check its output −
x: 10 Address of x: -1742755108
Address of y: -1742755104
Value at address in y: 10
How Does Call by Reference Work in C?
When a function is called by reference, the address of the actual argument variables passed, instead of their values.
Let us define the add() function that receives the references of two variables −
intadd(int*x,int*y){int z =*x +*y;return z;}
When such a function is called, we pass the address of the actual argument.
Example
Let us call the add() function by reference from inside the main() function −
#include <stdio.h>/* function declaration */intadd(int*,int*);intmain(){int a =10, b =20;int c =add(&a,&b);printf("Addition: %d", c);}intadd(int*x,int*y){int z =*x +*y;return z;}
Output
When you run this code, it will produce the following output −
Addition: 30
Now let’s understand how this code actually works. The main() function passes the address of a and b to the add() function. The addresses of a and b are assigned to the pointer variables x and y.
Now focus on the statement “z = *x + *y;” inside the add() function. Remember that x stores the address of a. The dereference operator in *x and *y fetches the values of a and b respectively, hence z is the addition of a and b in the main() function.
Example: Swap Values with Call by Reference
Let us understand in more detail how the Call by Reference mechanism works, with the help of the following example that interchanges value of two variables.
#include <stdio.h>/* Function definition to swap the values *//* It receives the reference of two variables whose values are to be swapped */intswap(int*x,int*y){int z;
z =*x;/* save the value at address x */*x =*y;/* put y into x */*y = z;/* put z into y */return0;}/* The main() function has two variables "a" and "b" *//* Their addresses are passed as arguments to the swap() function. */intmain(){/* local variable definition */int a =10;int b =20;printf("Before swap, value of a: %d\n", a );printf("Before swap, value of b: %d\n", b );/* calling a function to swap the values */swap(&a,&b);printf("After swap, value of a: %d\n", a);printf("After swap, value of b: %d\n", b);return0;}
Output
When you run this code, it will produce the following output −
Before swap, value of a: 10
Before swap, value of b: 20
After swap, value of a: 20
After swap, value of b: 10
Explanation
Assume that the variables a and b in the main() function are allotted locations with the memory address 100 and 200 respectively. As their addresses are passed to x and y (remember that they are pointers), the variables x, y and z in the swap() function are created at addresses 1000, 2000 and 3000 respectively.
Since “x” and “y” store the address of “a” and “b”, “x” becomes 100 and “y” becomes 200, as the above figure shows.
Inside the swap() function, the first statement “z = *x” causes the value at address in “x” to be stored in “x” (which is 10). Similarly, in the statement “*x = *y;“, the value at the address in “y” (which is 20) is stored in the location whose pointer is “x”.
Finally, the statement “*y = z;” assigns the “z” to the variable pointed to by “y”, which is “b” in the main() function. The values of “a” and “b” now get swapped.
The following figure visually demonstrates how it works −
Mixing Call by Value and Call by Reference
You can use a function calling mechanism that is a combination of Call by Value and Call by Reference. It can be termed as “mixed calling mechanism”, where some of the arguments are passed by value and others by reference.
A function in C can have more than one arguments, but can return only one value. The Call by Reference mechanism is a good solution to overcome this restriction.
Example
In this example, the calculate() function receives an integer argument by value, and two pointers where its square and cube are stored.
#include <stdio.h>#include <math.h>/* function declaration */intcalculate(int,int*,int*);intmain(){int a =10;int b, c;calculate(a,&b,&c);printf("a: %d \nSquare of a: %d \nCube of a: %d", a, b, c);}intcalculate(int x,int*y,int*z){*y =pow(x,2);*z =pow(x,3);return0;}
Output
When you run this code, it will produce the following output −
a: 10
Square of a: 100
Cube of a: 1000
The Call by Reference mechanism is widely used when a function needs to perform memory-level manipulations such as controlling the peripheral devices, performing dynamic allocation, etc.
Leave a Reply