• C Programming Video Tutorials

Function Call by Reference in C



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>

int main(){

   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>

int main(){

   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 −

int add(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 */
int add(int *, int *);

int main(){

   int a = 10, b = 20;
   int c = add(&a, &b);
   
   printf("Addition: %d", c);
}

int add(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 */

int swap(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 */
  
   return 0;
}

/* The main() function has two variables "a" and "b" */ 
/* Their addresses are passed as arguments to the swap() function. */

int main(){

   /* 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);
 
   return 0;
}

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.

Inside the swap in C

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 −

Understand Visually how this works in C

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 */
int calculate(int, int *, int *);

int main(){

   int a = 10;
   int b, c;

   calculate(a, &b, &c);

   printf("a: %d \nSquare of a: %d \nCube of a: %d", a, b, c);
}

int calculate(int x, int *y, int *z){

   *y  = pow(x,2);
   *z = pow(x, 3);

   return 0;
}

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.

Advertisements