📘 Lesson  ·  Lesson 55

Call by Value vs Reference

Two ways to pass arguments

When you call a function and give it some data, C needs to decide how that data reaches the function. There are two mental models, and the difference between them decides whether the function can change your original variable or not:

  • Call by value — the function gets a copy of the data. Your original is safe and unchanged.
  • Call by reference — the function gets the address of the data, so it can reach back and change the original.

C uses call by value by default. Call by reference is done using pointers. Let's see both.

Call by value: works on a copy

Here the function receives a copy of a. Changing that copy does nothing to the original.

C Language
#include <stdio.h>
void change(int x) {
    x = 100;        // changes only the local copy
}
int main() {
    int a = 5;
    change(a);
    printf("a = %d\n", a);   // still 5
    return 0;
}
Output:
a = 5

Even though change set x = 100, the original a stayed 5 — because x was just a copy that disappeared when the function ended.

Call by reference: works on the original

Now we pass the address of a instead. The function receives it as a pointer and changes the value at that address.

C Language
#include <stdio.h>
void change(int *x) {
    *x = 100;       // changes the original via its address
}
int main() {
    int a = 5;
    change(&a);      // pass the address of a
    printf("a = %d\n", a);   // now 100
    return 0;
}
Output:
a = 100

This time a became 100. The &a handed over a's address, and *x = 100 wrote directly into a's memory.

💡 Important truth

C is always call by value. "Call by reference" just means we pass a pointer (an address) by value — and because that address still points to the original, the function can change it.

The classic proof: swapping two numbers

This is the example every interviewer loves, because it shows the difference perfectly. First, the broken version with call by value:

C Language
#include <stdio.h>
void swap(int x, int y) {   // copies only
    int t = x; x = y; y = t;
}
int main() {
    int a = 5, b = 9;
    swap(a, b);
    printf("a = %d, b = %d\n", a, b);   // unchanged!
    return 0;
}
Output:
a = 5, b = 9

Nothing swapped — the function only shuffled its local copies. Now the working version with call by reference:

C Language
#include <stdio.h>
void swap(int *x, int *y) {   // addresses
    int t = *x; *x = *y; *y = t;
}
int main() {
    int a = 5, b = 9;
    swap(&a, &b);
    printf("a = %d, b = %d\n", a, b);   // swapped!
    return 0;
}
Output:
a = 9, b = 5

By passing addresses, the function reaches the real a and b and swaps them for good. This single comparison is the heart of the topic.

Call by value vs call by reference

PointCall by valueCall by reference
What is passedA copy of the valueThe address (a pointer)
Original variableCannot changeCan change
Called withchange(a)change(&a)
Received asint xint *x
Large data costCopies everythingCopies only an address

When to use which

  • Use call by value when the function only needs to read the data and should not touch the original.
  • Use call by reference when the function must change the caller's variable, return more than one result, or handle large data efficiently.

Common mistakes

  • Expecting a call-by-value function to change the original — it never can.
  • Forgetting the & when calling a reference function (passing the value instead of its address).
  • Forgetting the * inside the function, so you change the pointer instead of the value it points to.
  • Passing the address of a local variable and using it after that function returns.
🏋️ Practice

Write a function void addTax(float *price, float rate) that increases the price by a tax rate in place. Call it with the address of a price variable and confirm the original value changed.

Summary

  • Call by value passes a copy — the original variable is never changed.
  • Call by reference passes an address — the function can change the original.
  • C is technically always call by value; reference is done by passing a pointer.
  • Swapping two numbers works only with call by reference.
  • Use reference to modify the caller's data or to pass large data efficiently.

Frequently Asked Questions

What is the difference between call by value and call by reference in C?
In call by value, the function receives a copy of the argument, so changes inside the function do not affect the original variable. In call by reference, the function receives the address of the variable (through a pointer), so it can change the original directly.
Does C really have call by reference?
Strictly speaking, C only has call by value — it always copies the argument. "Call by reference" in C is simulated by passing a pointer (the address) by value. Since the copied pointer still holds the original address, the function can reach and change the original variable, which gives the effect of call by reference.
Why does a swap function not work with call by value?
Because the swap function only exchanges its local copies. The originals in the caller are untouched, so after the function returns they look exactly the same. To actually swap the caller's variables you must pass their addresses and swap through pointers.
How do I pass a variable by reference in C?
Pass its address using & when calling, and receive it as a pointer using * in the function. For example call change(&a) and define void change(int *x){ *x = 100; }. Inside, *x reads and writes the original variable.
Is call by reference faster than call by value?
For small values like a single int the difference is negligible. But for large data such as big structures, passing an address (reference) avoids copying the whole thing, so it is faster and uses less memory. That is a common real reason to pass by pointer.
← Back to C Tutorial
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

💻 Live Code Editor

This page's programs are ready here — run them, edit them, and learn. No installation needed.
Powered by OneCompiler. The code loads into the editor automatically — press Run to see the output. If the editor does not open, open it in a new tab.