Function Call by Reference in C

Hello there, future programmers! Today, we're going to embark on an exciting journey into the world of C programming, specifically exploring the concept of "Function Call by Reference." Don't worry if you're new to programming; I'll guide you through this step-by-step, just as I've done for countless students over my years of teaching. So, grab your favorite beverage, get comfortable, and let's dive in!

C - Function call by reference

The Address Operator (&) in C

Before we can understand function calls by reference, we need to familiarize ourselves with a very important symbol in C: the ampersand (&). This little character is known as the "address operator," and it's like a magical wand that reveals the secret location of our variables in the computer's memory.

Let's look at a simple example:

#include <stdio.h>

int main() {
    int age = 25;
    printf("The value of age is: %d\n", age);
    printf("The address of age is: %p\n", &age);
    return 0;
}

In this code, we're not just printing the value of age (which is 25), but also its address in memory. The %p format specifier is used to print memory addresses.

When you run this program, you might see something like:

The value of age is: 25
The address of age is: 0x7ffd5e8e9944

That strange-looking number after "The address of age is:" is actually a memory address! It's where your computer has decided to store the age variable. Think of it as the variable's home address in the vast neighborhood of your computer's memory.

What is a Pointer in C?

Now that we know how to find a variable's address, let's talk about pointers. If the address is like a home address, then a pointer is like a GPS navigator that can guide you to that address.

In C, a pointer is a variable that stores the memory address of another variable. We declare a pointer by using the asterisk (*) symbol.

Here's an example:

#include <stdio.h>

int main() {
    int age = 25;
    int *ptr_age = &age;

    printf("The value of age is: %d\n", age);
    printf("The address of age is: %p\n", &age);
    printf("The value of ptr_age is: %p\n", ptr_age);
    printf("The value ptr_age points to is: %d\n", *ptr_age);

    return 0;
}

In this code, ptr_age is a pointer that stores the address of age. When we use *ptr_age, we're asking for the value stored at the address that ptr_age is pointing to.

The output might look like this:

The value of age is: 25
The address of age is: 0x7ffd5e8e9944
The value of ptr_age is: 0x7ffd5e8e9944
The value ptr_age points to is: 25

See how the address stored in ptr_age matches the address of age? That's because ptr_age is pointing to age!

How Does Call by Reference Work in C?

Now that we understand pointers, we can explore function calls by reference. When we call a function by reference, we're passing the address of a variable to the function, rather than its value. This allows the function to directly modify the original variable.

Let's look at an example:

#include <stdio.h>

void increment(int *num) {
    (*num)++;
}

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

In this code, we're passing the address of x to the increment function. The function then uses this address to directly modify the value of x.

The output will be:

Before increment: x = 5
After increment: x = 6

The increment function was able to change the value of x in the main function because it received the address of x, not just a copy of its value.

Mixing Call by Value and Call by Reference

In C, we can mix call by value and call by reference in the same function. This can be useful when we want to modify some parameters but not others.

Here's an example:

#include <stdio.h>

void modify(int *a, int b, int *c) {
    (*a)++;
    b++;
    (*c)++;
}

int main() {
    int x = 1, y = 2, z = 3;
    printf("Before modify: x = %d, y = %d, z = %d\n", x, y, z);
    modify(&x, y, &z);
    printf("After modify: x = %d, y = %d, z = %d\n", x, y, z);
    return 0;
}

In this example, x and z are passed by reference, while y is passed by value.

The output will be:

Before modify: x = 1, y = 2, z = 3
After modify: x = 2, y = 2, z = 4

Notice how x and z changed, but y remained the same? That's because the function received only a copy of y's value, not its address.

Here's a table summarizing the differences between call by value and call by reference:

Aspect Call by Value Call by Reference
What's passed Copy of the value Address of the variable
Can modify original No Yes
Syntax function(variable) function(&variable)
Function parameter Normal variable Pointer

And there you have it! We've covered the basics of function calls by reference in C. Remember, like learning any new skill, practice is key. Try writing your own functions that use call by reference, and experiment with different scenarios. Before you know it, you'll be manipulating memory addresses like a pro!

Happy coding, and may your pointers always point in the right direction!

Credits: Image by storyset