Skip to main content

Call by Value vs Call by Reference in C πŸ”„

Mentor's Note: Think of passing arguments to functions like sharing documents. Sometimes you hand someone a photocopy of your notesβ€”they can scribble on it, but your original notes remain clean. Other times, you give them the key to your locker where the original document is storedβ€”any changes they make will affect your original document. Understanding this distinction is the key to mastering memory management in C! πŸ’‘

πŸ“š Educational Content: This topic is highly relevant for GSEB Std 11/12 (Theory & Practical), CBSE Class 11/12 Computer Science, and university BCA Sem 1 examinations. Writing the "Swap Function" is a classic board exam question that examiners use to test your pointer concepts.

What You'll Learn

By the end of this tutorial, you'll know:

  • The fundamental difference between Call by Value and Call by Reference.
  • How parameters are allocated memory on the stack.
  • Why the standard swap function fails in Call by Value.
  • How to implement a correct swap function using pointers in C.
  • How to select the right parameter-passing method for your program's needs.

🌟 The Scenario: The Photocopy Shop vs. The Shared Locker​

Imagine you have written a story on a sheet of paper. Your friend wants to edit it. You have two choices:

  1. The Photocopy Shop (Call by Value): You run to a photocopy machine, make a duplicate copy of your sheet, and hand the copy to your friend. Your friend takes a red pen, strikes out lines, and writes corrections. When they are done, does your original sheet of paper have any red ink? Absolutely not! The changes were restricted to the copy.
  2. The Shared Locker (Call by Reference): You put your original sheet of paper inside a school locker, lock it, and give your friend a duplicate key (or the locker address). Your friend opens the locker, takes out the original sheet, writes corrections directly on it, and puts it back. When you open the locker later, your original sheet has changed!

In C programming:

  • The sheet of paper is a Variable.
  • The photocopy represents Call by Value.
  • The locker address represents Call by Reference.

πŸ“– Concept Explanation​

In C, variables passed into functions are called arguments (or actual parameters), and the variables receiving them in the function definition are called parameters (or formal parameters). C uses two ways to pass these parameters.

1. Call by Value​

In Call by Value, the value of the actual parameter is copied into the formal parameter of the function.

  • Memory Allocation: The function's parameters are allocated separate memory locations on the call stack.
  • Scope Isolation: Any change made to the formal parameters inside the function has zero effect on the actual parameters in main().
  • Default Behavior: This is the default parameter-passing mechanism for primitive types (like int, float, char) in C.

2. Call by Reference (via Pointers)​

C is strictly a Call by Value language under the hood, but it simulates Call by Reference by passing the memory address of a variable instead of its value.

  • Pointers as Parameters: The function's formal parameters are declared as pointer variables (e.g., int *x).
  • Direct Modification: When you call the function, you pass the variable's address using the address-of operator (&a). Inside the function, you dereference the pointer using the asterisk operator (*x) to read or write directly to the caller's memory block.

Where is it used?​

  • Web Development / Systems: Passing database connection structs by reference to avoid duplicating heavy objects.
  • Enterprise Software: Passing configuration settings by value to prevent utility functions from accidentally modifying system-wide constants.

🧠 Algorithm & Step-by-Step Logic​

Let's design a program to swap (exchange) the values of two variables:

Call by Value Swap (Incorrect Logic)​

  1. Start 🏁
  2. Send values of a and b to swap_by_value(num1, num2).
  3. In swap_by_value, copy num1 to temp.
  4. Copy num2 to num1.
  5. Copy temp to num2. (Formal parameters are swapped).
  6. End (Notice that a and b in main remain unchanged). 🏁

Call by Reference Swap (Correct Logic)​

  1. Start 🏁
  2. Send addresses of a and b (&a and &b) to swap_by_reference(num1, num2).
  3. In swap_by_reference, dereference num1 and store the value in temp.
  4. Copy value at address num2 to the address pointed to by num1.
  5. Copy temp to the address pointed to by num2. (Memory cells of a and b are directly swapped).
  6. End (Values of a and b in main are successfully swapped). 🏁

πŸ’» Implementations​

Let's write both implementations in C to see the difference.

1. Call by Value: The Incorrect Swap​

#include <stdio.h>

// Incorrect swap function using Call by Value
void swap_by_value(int num1, int num2) {
int temp = num1;
num1 = num2;
num2 = temp;
printf("Inside function: num1 = %d, num2 = %d\n", num1, num2);
}

int main() {
int a = 10;
int b = 20;

printf("Before swap: a = %d, b = %d\n", a, b);

// Passing values of a and b
swap_by_value(a, b);

printf("After swap: a = %d, b = %d\n", a, b);
return 0;
}

// Output:
// Before swap: a = 10, b = 20
// Inside function: num1 = 20, num2 = 10
// After swap: a = 10, b = 20

Explanation: When swap_by_value(a, b) is called, the value of a (10) is copied into num1, and b (20) is copied into num2. Inside the function, the copies swap places. However, once the function finishes execution, its stack frame is destroyed. When control returns to main(), a and b still have their original values.


2. Call by Reference: The Correct Swap​

#include <stdio.h>

// Correct swap function using pointers (Call by Reference)
void swap_by_reference(int *num1, int *num2) {
int temp = *num1; // Store value at address num1 in temp
*num1 = *num2; // Assign value at address num2 to address num1
*num2 = temp; // Assign temp value to address num2
printf("Inside function: *num1 = %d, *num2 = %d\n", *num1, *num2);
}

int main() {
int a = 10;
int b = 20;

printf("Before swap: a = %d, b = %d\n", a, b);

// Passing addresses of a and b using the address-of operator (&)
swap_by_reference(&a, &b);

printf("After swap: a = %d, b = %d\n", a, b);
return 0;
}

// Output:
// Before swap: a = 10, b = 20
// Inside function: *num1 = 20, *num2 = 10
// After swap: a = 20, b = 10

Explanation: We pass &a and &b to swap_by_reference. The variables num1 and num2 are declared as pointers (int *), storing memory addresses. By using the dereferencing operator (*), we reach out of the function's local boundary and directly swap the values inside the memory cells of a and b.


πŸ“Š Sample Dry Run​

Let's trace how the variables change during swap_by_reference(&a, &b). Assume variable a is stored at memory address 0x100 and b is stored at 0x104.

StepInstructiona Value (at 0x100)b Value (at 0x104)num1 Valuenum2 Valuetemp ValueDescription
1int a = 10, b = 20;1020---Initial variables declared in main.
2swap_by_reference(&a, &b);10200x1000x104-Addresses are passed. Pointers point to variables.
3int temp = *num1;10200x1000x10410temp stores the value at address 0x100 (a).
4*num1 = *num2;20200x1000x10410Value at 0x104 (b) is written to address 0x100 (a).
5*num2 = temp;20100x1000x10410temp value (10) is written to address 0x104 (b).
6Function Ends2010---Stack frame destroyed. Swapping successful in main.

πŸ“‰ Complexity Analysis​

Time Complexity ⏱️​

  • Best, Average, and Worst Case: $O(1)$ - The parameter-passing and swapping logic require a constant number of memory accesses, making it run instantly regardless of input values.

Space Complexity πŸ’Ύβ€‹

  • Auxiliary Space: $O(1)$ - Only one extra temporary integer variable (temp) is created in memory.
  • Total Space: $O(1)$ - Memory does not grow dynamically.

🎨 Visual Logic & Diagrams​


πŸ“š Best Practices & Common Mistakes​

βœ… Best Practices​

  • Use const pointers when read-only is needed: If you pass a large struct by reference for speed but do not want it modified, declare it as const my_struct *ptr.
  • Check for NULL pointers: Before dereferencing pointers in a function, check if they are NULL to avoid segmentation faults.
    if (num1 == NULL || num2 == NULL) return;

❌ Common Mistakes βš οΈβ€‹

  • Passing Value instead of Address: Writing swap(a, b) when the function expects swap(&a, &b).
  • Forgetting to Dereference: Writing num1 = num2; instead of *num1 = *num2; inside the swap function. This swaps the addresses stored inside the pointer variables, not the actual values they point to!
  • Returning Local Address: Never return the address of a local variable from a function. Since local variables are destroyed when the function exits, returning their address results in a "dangling pointer" pointing to garbage memory.

🎯 Practice Problems​

Easy Level πŸŸ’β€‹

  1. Write a function double_value(int *x) that doubles the value of an integer variable using Call by Reference.
  2. Design a program that accepts an integer in main() and increments it by 5 using Call by Reference.

Medium Level πŸŸ‘β€‹

  1. Write a function find_stats(int arr[], int size, int *min, int *max) that finds the minimum and maximum values in an array and returns both values to main using Call by Reference.
  2. Implement a custom division function divide(int a, int b, int *quotient, int *remainder) that returns both results.

Hard Level πŸ”΄β€‹

  1. Write a function circular_shift(int *a, int *b, int *c) that rotates the values: a gets b's value, b gets c's value, and c gets a's value. Try to implement it without using more than one temporary variable.

❓ Frequently Asked Questions​

Q: Does C natively support Call by Reference?

No. C does not have native reference parameters (like C++ does with the & symbol in function signatures, e.g., void swap(int &a, int &b)). C strictly uses Call by Value. We achieve Call by Reference in C by passing pointer values (addresses) by value. Since the address is copied, we can dereference it to modify the original value.

Q: When should I choose Call by Value over Call by Reference?

Use Call by Value for small variables (like int, float, char) when you do not need to modify the original variable. This protects your original variable from being accidentally changed by the function. Use Call by Reference when you need to modify the original variable, return multiple values, or pass heavy data structures like structs (to save memory by not copying the structure).

Q: Why do C arrays always behave like Call by Reference?

In C, when you pass an array name as an argument to a function, it automatically "decays" into a pointer to its first element. Therefore, arrays are always passed by address, and any modifications to the array elements inside the function will change the original array.


βœ… Summary​

In this tutorial, you've learned:

  • βœ… Call by Value duplicates variable values, making modifications safe but isolated.
  • βœ… Call by Reference copies memory addresses using pointers, allowing direct changes to the caller's variables.
  • βœ… Swapping variables requires passing addresses (&a, &b) to function pointer parameters.
  • βœ… Memory efficiency is higher with Call by Reference for larger objects because only an address (4 or 8 bytes) is passed.
  • βœ… C is strictly Call by Value but simulates Call by Reference using pointers.

πŸ’‘ Interview Tips & Board Focus πŸ‘”β€‹

  • Board Exam Alert: You will often be asked: "Distinguish between Call by Value and Call by Reference in C with an example." Always write the definitions and then illustrate with both swap functions shown above.
  • Viva Voce Question: "What is the size of a pointer parameter passed in Call by Reference?" A pointer variable's size depends on the system architecture (4 bytes on 32-bit, 8 bytes on 64-bit), regardless of the data type it points to.
  • Key Terms to Mention: Formal parameters, actual parameters, stack frame allocation, dereferencing, address-of operator.

πŸ“š Further Reading​

Continue your learning path:

Go deeper:

πŸ“ Visit Us

🏫 VD Computer Tuition Surat

VD Computer Tuition
πŸ“ Address
2/66 Faram Street, Rustompura
Surat – 395002, Gujarat, India
πŸ“ž Phone / WhatsApp
+91 84604 41384
🌐 Website

Computer Classes & Tuition β€” Areas We Serve in Surat

Adajanβ€’Althanβ€’Amroliβ€’Athwaβ€’Athwalinesβ€’Bhagalβ€’Bhatarβ€’Bhestanβ€’Canal Roadβ€’Chowkβ€’Citylightβ€’Dumasβ€’Gaurav Pathβ€’Ghod Dod Roadβ€’Haziraβ€’Jahangirpuraβ€’Kamrejβ€’Kapodraβ€’Katargamβ€’Limbayatβ€’Magdallaβ€’Majura Gateβ€’Mota Varachhaβ€’Nanpuraβ€’New Citylightβ€’Olpadβ€’Palβ€’Pandesaraβ€’Parle Pointβ€’Piplodβ€’Punaβ€’Randerβ€’Ring Roadβ€’Rustampuraβ€’Sachinβ€’Salabatpuraβ€’Sarthanaβ€’Sosyo Circleβ€’Udhnaβ€’Varachhaβ€’Ved Roadβ€’Vesuβ€’VIP Road
πŸ“ž Call SirπŸ’¬ WhatsApp Sir