One way to see pointers is to make an analogy with names and addresses. Let’s say Alice lives at 42 X Street, Bob lives at 43 and Charlie at 44. If you only know Alice, but you don’t know or care where she lives, you can interact with her and only her.
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 in, you’ll find someone else in her place.
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 her 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 beware! If you stray too far from the known street, you may 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 noted "the value that’s in the address x
". But it’s nice to point out that x
is a variable like any other: it has a value, and exists in a memory position.
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 response from Lucas Virgili, one of the pointer utilities (in addition to traversing 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 memory position that used to hold something useful has now 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, pass pointers (or addresses) to functions you are calling is OK, return pointers or save them to the future, only if you know what you are doing.
Good afternoon, you can follow this tutorial from USP...is quite interesting and has examples for everything they explain. Enjoy. http://www.ime.usp.br/~pf/algoritmos/aulas/Pont.html
– Dante