The & extracts the memory address of a particular variable, which can be used for a wide variety of things.
Examples:
Suppose you want to create a function that adds an integer x to an integer variable y. What many laymen and beginners would do would be:
#include <stdio.h>
void adicionar( int x, int y){
y += x;
}
int main(){
int a = 5, b = 2;
printf("Valor inicial de b: %i\n", b);
adicionar(a, b);
printf("Valor final de b: %i", b);
return 0;
}
Output:
Valor inicial de b: 2
Valor final de b: 2
Yes, but we do not ask the function adicionar
to change the value of variable b?
Unfortunately this is not how things work: When we pass b to the function adicionar
, we pass a copy from b to the function. Why does it happen? Because the function called for the value contained in b, not its address in memory . In this way, it is impossible to change the original variable b.
We can think of this situation as follows: In function adicionar
:
void adicionar( int x, int y){
int x = x;
int y = y;
}
That is, when a function requests a valor
of a variable, it is as if it internally recreates the variables that we pass, only in a proper scope. In this way, the variables we pass as arguments are ignored, and the function scope variables are used.
To solve this unfortunate problem, an alternative would be to modify the add function as follows:
void adicionar( int x, int *y){
*y += x;
}
Here, we ask for a pointer for integer y. This basically means that we are requesting a memory address from a variable, that is, a location in memory that we will modify within the function. The *y += x
snippet basically causes the dereference of the y pointer, and adds the x value to that dereference. For ease of understanding, we could write the following pseudo-function code:
void adicionar( cópia de inteiro x, ponteiro para inteiro y){
Desreferencie, ou seja, obtenha o endereço de memória para o qual y aponta.
Em seguida, some a cópia do valor de x ao ponteiro recentemente desreferenciado.
}
In this case, we can do the following in our function main()
:
int main(){
int a = 5, b = 2;
printf("Valor inicial de b: %i\n", b);
adicionar( a, &b);
printf("Valor final de b: %i\n", b);
return 0;
}
Output:
Valor inicial de b: 2
Valor final de b: 7
But what is this &
that we enter before b by calling the add function? What he does? Very simple: It passes a pointer to a memory address! It's as if we were implicitly starting the y-parameter of our function with the address of b! In this way, when we dereferentiate y within the adicionar
function, we are causing the address of b, for which y is pointing, to have its modified value!
Therefore, we conclude that &
is an operator that allows us to access and modify a memory address of a variable.
We could also modify the contents of b without the use of functions using pointers indirection coupled with the use of the &
operator. For example:
#include <stdio.h>
int main(){
int a = 5, b = 2, *c = NULL;
c = &b; //c agora aponta para o endereço de b, obtido com o operador &.
*c += a; //O valor contido no endereço para qual c aponta (b) é igual a ele mesmo mais a.
printf("O valor de b é: %i", b);
return 0;
}
Output:
O valor de b é: 7
Another use of &
, less known by beginners, is to perform the logical AND operation. For example:
if((24 & 50) > 30){
puts("(24 & 50) é maior que 30.");
}
else{
puts("(24 & 50) é igual ou menor que 30.");
}
Knowing that &
represents, in this case, the logical AND operation, we obtain:
0 0 0 1 1 0 0 0
0 0 1 1 0 0 1 0
____________________________________
0 0 0 1 0 0 0 0
Since the result is 16 in the decimal base, the output of this conditional structure is:
(24 & 50) é igual ou menor que 30.