In part 1, we learned the basic ideas behind pointers, addresses, and what they mean. In part 2, we’re going to talk about one of the main uses for pointers, passing by reference. This part will be a little easier to wrap your head around and might make some of the concepts in part 1 a little more clear.
What is passing by reference?
In C, when you pass a variable to a function, you’re actually passing a copy of that variable to the function. Any operations taken upon that variable do not actually apply to the real variable.
Conversely, when we pass by reference, we are passing the address of the variable to a function, effectively giving the function the real variable.
Embrace my analogies…
I have a piece of paper with a list of all my friends’ favorite colors. I have a new friend, Lina, and I want to know her favorite color and keep a record of it.
I fax Lina a copy of my paper asking her to add her name and favorite color, then fax it back to me. Now, I can either update my original piece of paper with her favorite color, or use the copy she faxed back to me as the new canonical list. This is the equivalent of how we normally pass functions in C without pointers.
Alternatively, I could mail Lina the physical list, ask her to add her name and favorite color to it, and mail it back to me. This would ensure that the only paper I have is the complete list. This is the C equivalent of passing a variable’s address to a function, or passing by reference.
Pass by Reference: The Code
Again, if you can follow along, please do. Otherwise, just read through, I will share the program’s outputs.
To illustrate the difference between passing variable values and variable references, check out this simple program:
#include <stdio.h>
void add_five(int);
void ptr_add_five(int*);
int main() {
int var = 10;
// We pass the var variable by
// reference. Note that nothing
// happens to the value of var.
printf("The value of var before the function is %i\n", var);
add_five(var);
printf("The value of var after the function is %i\n", var);
// Now we will pass the variable
// by reference. Note that this time
// the actual value changes.
printf("The value of var before the function is %i\n", var);
ptr_add_five(&var);
printf("The value of var after the function is %i\n", var);
return 0;
}
void add_five(int x) {
x += 5;
printf("The add_five function fired\n");
}
void ptr_add_five(int *x) {
*x += 5;
printf("The ptr_add_five function fired\n");
}
Here’s the output:
The value of var before the function is 10
The add_five function fired
The value of var after the function is 10
The value of var before the function is 10
The ptr_add_five function fired
The value of var after the function is 15
See what I mean now? We have 2 relatively identical functions, each adding five to the parameter they were passed. The function creates a new value by grabbing some separate memory addresses, assigning them the value of 5, and then we’ll never really see it again. Inside that function, x will be 15, yes, but once we get back to the main
function, that variable is pretty much gone.
The function that takes a pointer instead has the address of the variable we want to manipulate. It takes the address, goes and finds the value at that address, and then adds five to it. That’s why when the program returns to the main
function, the value of the variable has changed.
Most of the time when C passes variables to a function, it is passing by value. Arrays, however, are not. In fact, the way C handles the passing of arrays to functions is by passing the address of the array’s first value to the function, which will then use pointer arithmetic to figure out how to transverse the array, which leads nicely into part 3.