Concetti Chiave
- I puntatori sono variabili che contengono l'indirizzo di memoria di altre variabili, consentendo l'accesso e la manipolazione della memoria nell'Heap.
- Per assegnare l'indirizzo di una variabile a un puntatore, si utilizza il simbolo &; per accedere al valore di una variabile tramite un puntatore, si usa il simbolo *.
- È fondamentale dichiarare il tipo di variabile a cui un puntatore fa riferimento per evitare problemi di compatibilità.
- È buona pratica inizializzare i puntatori a NULL per evitare errori, e occorre gestire correttamente la memoria per prevenire memory leak.
- Puntatori e array sono strettamente correlati, poiché un array rappresenta l'indirizzo del primo elemento, rendendo i puntatori simili a un array.
I Puntatori
La memoria del calcolatore è divisa in Stack e Heap.
Nello Stack, o memoria statica, sono immagazzinate tutte le variabili, come la classica x. Nell’Heap, o memoria dinamica, vi è la possibilità di allocare ma anche di de-allocare la memoria. Questa manipolazione dell’heap avviene proprio grazie ai puntatori.
Un puntatore è una variabile che contiene l’indirizzo di memoria di un’altra variabile. Per assegnare ad un puntatore ( p_x ) l’indirizzo di una variabile ( x ) si usa il simbolo &, quindi si avrà:
p_x = & x ;
come si può vedere dall’immagine sopra, se immaginiamo che x sia una variabile intera assegnata all’indirizzo di memoria 7500, se p_x fa riferimento alla cella di x, p_x conterrà infine 7500.
Se si vuole accedere al contenuto di un puntatore bisognerà invece utilizzare il simbolo ( * ). Quindi scrivendo:
p_x = & x;
*p_x = 20;
non facciamo altro che connettere p_x all’indirizzo della cella di memoria in cui si trova x. Successivamente assegniamo il valore 20 al puntatore p_x che punta alla cella di memoria di x. Pertanto infine avremo x = 20.
Quindi sarà indifferente scrivere: x = 20 o *p_x = 20
Per definire una variabile di tipo puntatore è necessario dichiarare il tipo di variabile puntatore, ossia a che tipo di variabile il puntatore faccia riferimento, seguito da un *. Quindi una dichiarazione di esempio può essere:
int *p_x; char *p_x; double *p_x;
Bisogna stare molto attenti al tipo di variabile che assegniamo infatti se il puntatore puntasse a variabili di tipo differente da quello dichiarato si potrebbero avere alcuni problemi!!!!
Per quanto riguarda invece l’inizializzazione di un puntatore questa avviene col comando &, come visto precedentemente. Tuttavia è buona norma inizializzare il puntatore a NULL, cioè a nessuna cella di memoria.
Se volessimo invece inizializzare il puntatore ad un valore dovremmo scrivere: p_x = new int (20)
Ricorda inoltre che agendo nello Slack si può andare incontro al memory leak. E’ quindi necessario distruggere il puntatore prima di riutilizzarlo e questo va fatto col comando “delete p_x;”.
Puntatori ed Array sono strettamente legati fra loro. Infatti un Array è semplicemente un valore costante che indica l’indirizzo del primo elemento del vettore. Pertanto un puntatore è simile ad un Array. Infatti se:
float f_array[MAX_size];
float* f_array2;
f_array2 = f_array;
allora si ha l’equivalenza: f_array2 = & f_array[0];
Utilizzare i puntatori però portano anche ad alcuni errori. Tra i più frequenti abbiamo:
- Puntatori non inizializzati = se saltiamo il codice con &.
- Comparazione tra puntatori non valida;
- Dimenticare di “resettare” un puntatore = se siamo in un ciclo;
‘ * ‘ = riguarda il contenuto
‘ & ‘ = riguarda l’address
Domande da interrogazione
- Che cos'è un puntatore e come viene utilizzato nella memoria del calcolatore?
- Qual è la differenza tra Stack e Heap nella gestione della memoria?
- Come si inizializza correttamente un puntatore e quali sono le buone pratiche da seguire?
- Quali sono gli errori comuni nell'uso dei puntatori?
Un puntatore è una variabile che contiene l'indirizzo di memoria di un'altra variabile. Viene utilizzato per manipolare la memoria dinamica (Heap) e si assegna con il simbolo &. Per accedere al contenuto di un puntatore si usa il simbolo *.
Lo Stack è la memoria statica dove sono immagazzinate le variabili, mentre l'Heap è la memoria dinamica che permette di allocare e de-allocare memoria tramite i puntatori.
Un puntatore si inizializza con il comando & e si consiglia di inizializzarlo a NULL per evitare errori. È importante distruggere il puntatore con "delete" per prevenire memory leak.
Gli errori comuni includono puntatori non inizializzati, comparazioni non valide tra puntatori, e dimenticare di resettare un puntatore, specialmente nei cicli.