By the end of this lecture, students will be able to:
In C programming, when we call a function and pass arguments to it, there are different ways these arguments can be passed. The two primary methods are:
Understanding these concepts is crucial for effective memory management and achieving desired program behavior.
In call by value, a copy of the actual parameter's value is passed to the function. The function works with this copy, and any changes made to the parameter inside the function do not affect the original variable.
Changes to 'copy' don't affect 'x'
#include <stdio.h>
// Function that receives value by copy
void increment(int num) {
num = num + 1; // This only changes the local copy
printf("Inside function: num = %d\n", num);
}
int main() {
int x = 10;
printf("Before function call: x = %d\n", x);
increment(x); // Pass value of x
printf("After function call: x = %d\n", x);
return 0;
}
Notice that the value of 'x' in main() remains unchanged (10) even though 'num' was incremented inside the function. This demonstrates that the function worked with a copy of the original value.
In call by reference, the address of the actual parameter is passed to the function. The function receives a pointer to the original variable, allowing it to directly modify the original value.
Changes through 'ptr' directly affect 'x'
#include <stdio.h>
// Function that receives address (reference)
void increment(int *num) {
*num = *num + 1; // This changes the original value
printf("Inside function: *num = %d\n", *num);
}
int main() {
int x = 10;
printf("Before function call: x = %d\n", x);
increment(&x); // Pass address of x
printf("After function call: x = %d\n", x);
return 0;
}
The value of 'x' in main() has changed to 11 because the function modified the original variable through its address. The function parameter 'num' is a pointer that points to the memory location of 'x'.
#include <stdio.h>
// This won't work - call by value
void swap_incorrect(int a, int b) {
int temp = a;
a = b;
b = temp;
printf("Inside function: a = %d, b = %d\n", a, b);
}
int main() {
int x = 5, y = 10;
printf("Before swap: x = %d, y = %d\n", x, y);
swap_incorrect(x, y);
printf("After swap: x = %d, y = %d\n", x, y);
return 0;
}
#include <stdio.h>
// This works - call by reference
void swap_correct(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
printf("Inside function: *a = %d, *b = %d\n", *a, *b);
}
int main() {
int x = 5, y = 10;
printf("Before swap: x = %d, y = %d\n", x, y);
swap_correct(&x, &y); // Pass addresses
printf("After swap: x = %d, y = %d\n", x, y);
return 0;
}
| Aspect | Call by Value | Call by Reference |
|---|---|---|
| Parameter Passed | Copy of actual value | Address of actual variable |
| Memory Usage | More (due to copying) | Less (only address is copied) |
| Original Data Safety | Safe (cannot be modified) | Can be modified accidentally |
| Function Parameter | Regular variable | Pointer variable |
| Function Call Syntax | function_name(variable) | function_name(&variable) |
| Function Definition | return_type func(datatype param) | return_type func(datatype *param) |
| Access Value | Direct access | Through dereference (*) |
| Performance | Slower for large data | Faster (no copying overhead) |
| Use Case | When original data should not change | When function needs to modify original data |
Arrays are always passed by reference in C (array name represents the address of first element):
#include <stdio.h>
void modify_array(int arr[], int size) {
// Arrays are passed by reference automatically
for(int i = 0; i < size; i++) {
arr[i] = arr[i] * 2; // Modifies original array
}
}
void display_array(int arr[], int size) {
for(int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int numbers[] = {1, 2, 3, 4, 5};
int size = 5;
printf("Original array: ");
display_array(numbers, size);
modify_array(numbers, size); // No & needed for arrays
printf("Modified array: ");
display_array(numbers, size);
return 0;
}
#include <stdio.h>
// Function to perform multiple operations and return multiple results
void calculate(int a, int b, int *sum, int *diff, int *product) {
*sum = a + b;
*diff = a - b;
*product = a * b;
}
int main() {
int num1 = 15, num2 = 5;
int addition, subtraction, multiplication;
printf("Numbers: %d and %d\n", num1, num2);
// Pass addresses to get multiple results
calculate(num1, num2, &addition, &subtraction, &multiplication);
printf("Sum: %d\n", addition);
printf("Difference: %d\n", subtraction);
printf("Product: %d\n", multiplication);
return 0;
}
#include <stdio.h>
// Using const to prevent accidental modification
void print_value(const int *ptr) {
printf("Value: %d\n", *ptr);
// *ptr = 100; // This would cause compilation error due to const
}
// Function that safely modifies the value
void safe_increment(int *ptr) {
if (ptr != NULL) { // Always check for null pointer
(*ptr)++;
}
}
int main() {
int x = 42;
print_value(&x); // Safe - cannot modify x
safe_increment(&x); // Safe - with null check
print_value(&x);
return 0;
}
Problem: Write a C program that includes the following functions:
Hint: Think about which functions need to modify original data and which ones don't.
In this lecture, we explored the fundamental concepts of parameter passing in C:
Next Lecture Preview: We will explore advanced pointer concepts and dynamic memory allocation.