The hardest thing for me to understand about C (and C++ as an heir to C) were the pointers, even the time and they still manage to confuse me.
There is a certain characteristic that I have not fully understood, I have only mechanized its correct operation and it is the passing of pointers by reference to functions.
I understand that in C, accessing the reference of an automatic variable with the ampersand(&) gets the memory address of that variable and in turn pointers are variables that point to memory addresses; pointers store memory addresses.
Two types of parameters can be passed to a C function (variics excluded): value-parameters and reference-parameters. The following example is the correct use of a parameter passed by reference to an automatic variable:
void funcion_init(int *varRef)
{
*varRef = 10;
}
int numero = 0;
funcion_init(&numero);
printf("%d", numero);
the variable numero
after executing that example will be 10, so far there is no problem, but from here on it is the problem. Making the following modifications to the previous example:
void funcion_init(int *varRef)
{
*varRef = 10;
}
int *numero = malloc(sizeof(int));
*numero = 0;
funcion_init(numero);
printf("%d", *numero);
Executing this example the result will be 0 and not 10 as expected, here we have to do something that doesn't make much sense to me: pass a pointer by reference. But aren't pointers supposed to be memory addresses themselves?
void funcion_init(int **varRef)
{
**varRef = 10;
}
int *numero = malloc(sizeof(int));
*numero = 0;
funcion_init(&numero);
printf("%d", *numero);
When using the ampersand(&) to a pointer that stores a memory address to be passed as a reference to a function, what is being passed to the function, the memory address of a memory address?
What is the logic behind this?
You have a serious mess of concepts, I'm going to put it big and bold to make it clear:
In the c language there are no references.
When you say:
You're wrong, you pass pointers by copy (not by reference) to functions.
When you say:
You're wrong, in C you can't access the reference of anything because in C references don't exist.
When you say:
You're wrong, the only way to pass parameters to C functions is by copy.
When you say:
You are wrong, you are copying a pointer inside a function, it is not a parameter by reference because in the C language references do not exist.
To know the difference between pointer and reference read this thread that talks about the differences between pointer and reference in a language that DOES have references.
Now I am going to illustrate with ASCII art what is happening in your examples:
First example:
We have an integer (
numero
), the functionfuncion_init
receives a pointer to an integer calledvarRef
into which the memory address ofnumero
:The et ( ) operator
&
gets the memory address of a variable, which is copied into a pointer in the same way that you copy numbers into numeric variables:In general we use the verb assign to the action of copying a value into a variable, so we are assigning value to
valor
yx
.Second example:
The function
malloc
reserves a memory space and returns a pointer to that space, you copy that pointer tonumero
and then copy it tovarRef
:It will print
10
, because both pointers point to the same memory.Third example:
The function
malloc
allocates a memory space and returns a pointer to that space that you copy to pointernumero
, the functionfuncion_init
receives a pointer to pointer to integer calledvarRef
where you copy the address ofnumero
which is a pointer and ask for its address gives a pointer to pointer :To better understand pointers, I recommend reading this thread .
First you must understand that in C language, the concept of passing by reference does not exist, because it is not possible to declare a reference as it is done in other languages such as C++.
So let's remember three concepts:
pass by reference : It means that you will pass the original variable to a reference , therefore, during the execution of a function, we will be able to alter the content of the original variable .
pass by value : Means that you will pass a copy of the original variable to a parameter.
pass by pointer : It means that you will pass the original variable to a pointer , therefore, during the execution of a function, we will be able to alter the content of the original variable .
I want to make it clear that in C we don't use the concept of pass by reference , but pass by pointer , which basically do the same thing, but the way of using it is different.
Example 1):
In this example it is being passed by pointer and this is because the memory address of the variable
numero
is received by a pointer (ieint* varRef
). Therefore, we can alter the content of the variablenumero
.Example (2):
The result on the screen is
10
and this is because in this example if it is being passed by value, that is, a copy of the content of is being sentnumero
, which precisely coincides with the memory address of the space that has been reserved withmalloc
.Note: Here we are not passing the pointer because we are not passing the original variable (in this case it is
int* numero
), therefore, we can never alter the content ofnumero
.Then, during the execution of said function, we can modify the content of said space (the one you reserved with
malloc
).Answering your question:
Yes, pointers internally consume a memory space, where they store a memory address of variable X.
A memory representation would look like this:
In this representation, the address
0x04
is that of the pointer, where it stores the address0x06
(which stores the value0
). So when you run this function:What you 're actually passing is the address
0x06
, and to do this, you must first access the content of the pointer (which in our example is hosted by the address0x04
).Example (3):
In this example we are passing by pointer and this is because what we are actually passing is the memory address (which for us is the original variable ) of the pointer
numero
. So since the parametervarRef
is a double pointer, it can store the memory address of a pointer, therefore, we can alter two things during the execution offuncion_init
:The content of the pointer
numero
.The content of the memory space that was reserved with the
malloc
.Answering your question:
Not exactly, what you're passing is simply a memory address .
We check it with this memory diagram:
When this function runs:
What you're passing is the memory address where the pointer is located
numero
, in this case, at address0x04
. Therefore, what the parametervarRef
actually receives is the memory address of the pointer, that is, the address0x04
.FAQ:
Are arrays in C passed by reference?
Answer: No. Because the concept of passing by reference in C does not exist.
What we could say is that arrays are passed by pointer , because what you are really passing is the original variable , which obviously coincides with the memory address of the first element of the array and therefore, we can modify the original array .
Conclusion:
Don't use the term pass by reference in C, it's confusing. Ideally, replace it with the term pass by pointer .
chic @, in any of the 3 cases the result is 10
The usefulness of a pointer to pointer is very little if you try to see it from the perspective of a single variable. Once you go to more dimensions the utility comes out.
Please note this code
when you make an arrangement. you will always be using pointers. So you can do stuff like this:
Since you know that whenever you work with arrays, you also work with pointers, so you can point to a two-dimensional array with double pointers. You will have noticed that all programs start with
so since argv is an array, it can also be referenced with pointers. So you can write it as:
So a double pointer can be said to be an array of pointers. and a triple pointer is an array of arrays of pointers.
The second
Because of how c works, all arguments passed to functions are copies of the variable you pass to it. This is why passing the argument by reference is important. When you pass a pointer, you are passing a copy of the memory address it stores. And there is no difference between using "&" or pointer.
For instance