Il puntatore è una variabile che punta ad un altra.
Che vuol dire?
Normalmente quando andiamo a definire una variabile, il nostro computer la mette da qualche parte nella memoria RAM.
Example
Supponiamo di aver definito la variabile
int main(){ int x = 3;}
quando andiamo ad eseguire il programma, il nostro computer la mette nello stack. In memoria risulta una cosa del genere:
nome variabile
contenuto
indirizzo
x
3
0x12345678
Quindi ogni variabile ha un valore, un nome, ed un indirizzo.
bene, quindi cos’è un puntatore?
Un puntatore è una variabile che, invece di contenere un qualsiasi numero, contiene un indirizzo in memoria! Per esempio:
Example
Potrei allocare una variabile puntatore chiamata p così
int main(){ int x = 3; int * p;}
Questo è il modo per dichiarare un puntatore ad un intero.
Per il momento questo puntatore non punta a nulla, in memoria quindi c’è solo il nome e l’indirizzo della variabile, ma non c’è nessun “contenuto”, quindi la variabile non punta a nulla.
Questo è il contenuto della memoria se eseguiamo il programma:
nome variabile
contenuto
indirizzo
x
3
0x12345678
p
0x39184233
Ora però il nostro puntatore non punta a nulla, per esempio potremmo voler farlo puntare alla variabile x di prima! Come facciamo?
Va bene fare così?
int main(){ int x=3; int * p; p=x;}
NO! non va bene fare così.
Perchè?
Perchè noi vogliamo ad assegnare a p, non il valore di x, ma il suo indirizzo. Cioè, non vogliamo questo:
nome variabile
contenuto
indirizzo
x
3
0x12345678
p
3
0x39184233
Noi vogliamo questo:
nome variabile
contenuto
indirizzo
x
3
0x12345678
p
0x12345678
0x39184233
Cioè vogliamo p che punti alla variabile x
graph LR;
p-->x=3
Quindi quello che vogliamo è che p assuma come valore l’indirizzo della variabile x (che nel nostro esempio è 0x12345678).
Per fare questo basta fare così:
int main(){ int x=3; int *p; p=&x}
Quando diciamo “&x” intendiamo l’indirizzo di memoria della variabile x.
Bene, ora il puntatore p “punta” alla variabile x.
nome variabile
contenuto
indirizzo
x
3
0x12345678
p
0x12345678
0x39184233
graph TD;
p-->x=3
Adesso, siccome x è puntata da p, possiamo stampare il contenuto di x usando p invece che x stessa? Domanda retorica, certo che si, ma come si fa?
Devo sostanzialmente dire “il contenuto della variabile puntata da p”.
In C per dire “il contenuto della variabile puntata da p” si usa “*p”
int main(){ int x=3; //dichiaro x int *p; //dichiaro il puntatore p=&x; //assegno al puntatore l'indirizzo di memoria della variabile x printf("%d",*p); // stampo il contenuto della variabile puntata da p}
Test per capire se hai capito
Prendi questo main
int main(){ int x=3; int p=&x;}
Se eseguito in memoria avrò questa situazione:
nome variabile
contenuto
indirizzo
x
3
0x12345678
p
0x12345678
0x39184233
Cosa stampa se stampo "x"?
stampa il valore della variabile x, cioè 3
cosa stampa se stampo &x?
stampo l’indirizzo di memoria di x, cioeè 0x12345678
Cosa stampa se stampo p?
Stampa il contenuto della variabile p, cioè 0x12345678, cioè l’indirizzo di memoria di x, visto che p punta ad x.
cosa stampa se stampo "&p"?
Stampa l’indirizzo di memoria della variabile p, cioè 0x39184233 nel nostro esempio.
Test per capire se hai capito
Prendi questo main
int main(){ int x=6; printf("%d",&x);}
Supponi che in memoria ci sia questo:
nome variabile
contenuto
indirizzo
x
3
0x12345678
Cosa stampa la printf?
La printf stamperà l’indirizzo di memoria di x, in questo caso 0x12345678 (o la traduzione in intero di questi byte, per i più nerd)