Call by Value and Call by Reference in C

What is Call by Value and Call by Reference in C ?

When passing arguments to functions in C, we have two ways to do it: call by value and call by reference. The fundamental difference lies in how the arguments are passed and manipulated within the function.

1. Call by Value

In call by value, a copy of the argument’s value is passed to the function. This means that any changes made to the parameter within the function do not affect the original variable in the calling code. Call by value is ideal for scenarios where you want to protect the original data from being altered.

2. Call by Reference

On the other hand, call by reference passes the memory address of the argument to the function. As a result, any changes made to the parameter within the function directly affect the original variable in the calling code. Call by reference is particularly useful when you need to modify the original data and save memory by avoiding the creation of duplicate copies.

Pros and Cons of Call by Value and Call by Reference

To better understand the differences between call by value and call by reference, let’s compare their pros and cons side by side:

AspectCall by ValueCall by Reference
Data PassingA copy of the argument’s value is passed to the function.The memory address of the argument is passed to the function.
Original DataRemains unaffected as changes occur on the copied data.Directly modified, reflecting changes outside the function.
Data IntegrityEnsured as the original data is protected from alterations.At risk due to direct modifications of the original data.
Memory ConsumptionConsumes additional memory for the copied data.Memory-efficient as it avoids data duplication.
Function ComplexitySimpler to implement and understand.Requires managing pointers and careful memory handling.
Suitable forSimple data types or small structures.Large data structures and situations needing data sharing.
OverheadPotential decrease in performance due to copying data.Slightly faster due to no data copying overhead.

When to Use Call by Value or Call by Reference

The decision between call by value and call by reference should be based on the specific requirements and constraints of your code. Here are some guidelines to help you make the right choice:

1. Use Call by Value When:

  • You want to protect the original data from being altered.
  • Predictable output is essential, and you don’t need to modify the original variables.
  • You are dealing with simple data types or small structures where the overhead of copying data is not significant.

2. Use Call by Reference When:

  • You need to modify the original data and reflect those changes outside the function.
  • Memory efficiency is critical, especially for large data structures or when dealing with limited memory resources.
  • You want to share data between functions without returning multiple values.

Example: Call by Value

Suppose we’re working on a program to calculate the factorial of a number. We want to create a function that calculates the factorial and returns the result, but we also want to keep the original number intact.

#include <stdio.h>

int factorial(int num) {
    int result = 1;
    for (int i = 1; i <= num; i++) {
        result *= i;
    }
    return result;
}

int main() {
    int number = 5;
    printf("Original number: %d\n", number);
    int result = factorial(number);
    printf("Factorial: %d\n", result);
    printf("Original number after function call: %d\n", number);
    return 0;
}

In this example, the factorial function is called by value. The value of the variable number is passed to the function, and any changes made to num inside the function do not affect the original number in the main function. This ensures that the original value of number remains unchanged.

Example: Call by Reference

Let’s consider a scenario where we want to swap the values of two variables using a function. Since we need to modify the original variables, we’ll use the call by reference approach.

#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    printf("Before swap: x = %d, y = %d\n", x, y);
    swap(&x, &y);
    printf("After swap: x = %d, y = %d\n", x, y);
    return 0;
}

In this example, the swap function is called by reference. It takes pointers to the variables x and y, allowing it to directly modify the original values of these variables. As a result, the values of x and y are swapped after the function call.

More Example: Swapping Two Numbers

#include <stdio.h>

// Call by Value - Doesn't swap the original numbers
void swapByValue(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

// Call by Reference - Swaps the original numbers
void swapByReference(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;

    printf("Original numbers: x = %d, y = %d\n", x, y);

    swapByValue(x, y);
    printf("After swapByValue: x = %d, y = %d\n", x, y);

    swapByReference(&x, &y);
    printf("After swapByReference: x = %d, y = %d\n", x, y);

    return 0;
}

Output:

Original numbers: x = 5, y = 10
After swapByValue: x = 5, y = 10
After swapByReference: x = 10, y = 5