MORENO SARDELLA · CORSO BASE
← Tutte le lezioni
Lezione 8

I PUNTATORI

Ogni variabile vive a un certo indirizzo nella RAM. Un puntatore è una variabile speciale che, invece di un valore, contiene un indirizzo: il "dove si trova" un dato. È il concetto che spaventa di più, ma con i disegni della memoria diventa chiaro.

01
L'idea

Indirizzi in memoria

La RAM è fatta di celle, ognuna con un proprio indirizzo (un numero, scritto in esadecimale, es. 0x0000AAAA). Una variabile occupa una cella. Un puntatore è una variabile che contiene l'indirizzo di un'altra variabile.

variabile x 42 0x0000AAAA puntatore p 0x0000AAAA 0x0000BBBB punta a p contiene l'indirizzo di x: *p vale 42
p non contiene 42, ma l'indirizzo dove sta 42. Seguendo la freccia (*p) si arriva al valore.
puntatori.cpp
int x = 42;
int *p = &x;          // p riceve l'indirizzo di x
cout << x;            // 42  (il valore)
cout << &x;           // 0x0000AAAA  (l'indirizzo)
cout << *p;           // 42  (il valore puntato)
*p = 100;            // modifica x passando dal puntatore
cout << x;            // 100
02
Il punto chiave

Per valore o per riferimento

Quando passi una variabile a una funzione puoi farlo in due modi, con conseguenze opposte sulla memoria.

Passaggio per valore (copia)

La funzione riceve una copia del valore, in una cella diversa (indirizzo diverso). Le modifiche restano dentro la funzione: la variabile originale non cambia.

x nel main 5 0x0000AAAA n nella funzione (copia) 5 → 10 0x0000CCCC celle diverse: raddoppiare n non tocca x x resta 5
Per valore: due celle indipendenti. La funzione lavora sulla copia.
per_valore.cpp
void raddoppia(int n) {   // n e' una COPIA
    n = n * 2;             // modifica solo la copia
}
int x = 5;
raddoppia(x);
cout << x;                 // stampa 5 (invariato!)

Passaggio per riferimento / indirizzo

La funzione lavora sulla stessa cella dell'originale (tramite un riferimento & o un puntatore *). Le modifiche restano anche fuori dalla funzione.

x nel main 5 → 10 0x0000AAAA n (riferimento) alias di x stessa cella: raddoppiare n cambia x → x diventa 10
Per riferimento: n è un altro nome per la stessa cella di x.

Riferimento (&)

void raddoppia(int &n) { n = n * 2; } // raddoppia(x); -> x = 10

Puntatore (*)

void raddoppia(int *n) { *n = *n * 2; } // raddoppia(&x); -> x = 10
Perché è utile — passare per riferimento permette a una funzione di "restituire" più valori (modificandone diversi), ed evita di copiare grandi quantità di dati (es. vettori e matrici, che si passano sempre senza copia).
03
Esercizi

Gli esercizi

Base: indirizzi, dereferenziazione, scambio e passaggio per riferimento. Avanzati: aritmetica dei puntatori, struct per puntatore e funzioni che restituiscono più valori (10 esercizi ciascuna).

Puntatori — basescarica ↓
Puntatori — avanzatiscarica ↓