One way to see pointers is to make an analogy with names and addresses. Let's say that Alice lives at number 42 on X street, Bob lives at number 43 and Charlie at 44. If you only know Alice but do not know or care about where she lives, you can interact with her and only her. p>
int array[3] = {10, 20, 30};
int x = array[0]; // Você conhece o valor 10, mas não sabe em que posição de memoria ele está
int y = x + x; // Você pode fazer operações com essa valor
array[0] = 40; // Se o valor do array mudar
printf("%d", x); // x continua sendo 10
x = 50;
printf("%d", array[0]); // E vice-versa (40)
On the other hand, if all you know is where Alice lives, then you have to go there to meet her. If she moves, you'll find someone else instead.
int array[3] = {10, 20, 30};
int *x = &array[0]; // Dessa vez você salvou a posição de memória em que o valor 10 está
// &v significa "o endereço de v"; x não contém 10, mas o endereço do 10
int y = *x + *x; // Se o 10 ainda estiver lá, você pode fazer operações com ele
// *x significa "o valor no endereço x"; ou seja, 10
array[0] = 40; // Se o valor do array mudar
printf("%d", *x); // *x passa a ser 40
// x não mudou, continua sendo o mesmo endereço; o ocupante do endereço é que mudou
Also, if you have Alice's address, you can visit your neighbors.
int array[3] = { 10, 20, 30 };
int *x = &array[0]; // x guarda o endereço do primeiro valor do array (10)
printf("%d", *x); // 10
x++; // Ao incrementar o x, ele passa a guardar o endereço do valor seguinte
printf("%d", *x); // 20
x++;
printf("%d", *x); // 30
But be careful! If you get too far off the known street, you can end up anywhere; probably a dangerous place ...: P
x++; // O 30 está numa posição de memória qualquer; na posição seguinte, tem alguma
// coisa, mas você não sabe o que é.
printf("%d", *x); // Um valor inesperado, ou segmentation fault
So far, I've only given examples that looked at "the value that is in the x
address". But it's good to note that x
is a variable like any other: it has a value, and exists in a memory location.
int array[3] = {10, 20, 30};
int *x = &array[0];
printf("%d", x); // Aqui ele vai imprimir o endereço em memória do 10;
// pode ser qualquer coisa, inclusive mudar de uma invocação pra outra
int **z = &x; // Agora z tem a posição de memória onde está x
*z++; // Se ele incrementar o valor que está lá
printf("%d", x); // x passa a ser o endereço em memória do 20
printf("%d", *x); // 20
Addendum: As demonstrated in the Lucas Virgili response , one of the utilities of pointers (besides running arrays, arrays, etc., and creating data dynamically via malloc
etc) is to allow a function to change values that only exist outside that function. But you have to be careful, because sometimes the position of memory that once held something useful now has already been "recycled" to something else:
int *foo() {
int x = 42; // O valor 42
int *y = &x; // O endereço de memória onde 42 está
return y;
}
...
int *z = foo(); // O endereço de memória onde o 42 estaVA
bar();
printf("%d", *z); // (foo já terminou, então suas variáveis locais não estão necessariamente na mesma
// posição de memória - ou sequer ainda existem [garantidamente])
As a rule, passing pointers (or addresses) to functions you are calling is OK, returning pointers or saving them for the future, only if you know what you are doing.