Concetti Chiave
- La memoria del calcolatore è divisa in Stack, per variabili statiche, e Heap, che consente l'allocazione e de-allocazione dinamica tramite puntatori.
- I puntatori sono variabili che contengono l'indirizzo di memoria di un'altra variabile e possono essere utilizzati per modificare il valore a cui puntano.
- La dichiarazione di un puntatore richiede di specificare il tipo di variabile a cui fa riferimento, seguita da un asterisco (*), e inizializzarlo a NULL è una buona prassi.
- Puntatori e array sono strettamente correlati, poiché un array rappresenta l'indirizzo del suo primo elemento e può essere assegnato a un puntatore.
- È importante gestire correttamente i puntatori per evitare errori comuni, come puntatori non inizializzati e dimenticanze nel reset durante i cicli.
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.
Come funziona un puntatore?
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
Dichiarazione e inizializzazione dei puntatori
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 e array
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
- Qual è la differenza principale tra Stack e Heap nella memoria del calcolatore?
- Come si assegna l'indirizzo di una variabile a un puntatore?
- Qual è l'importanza di inizializzare un puntatore a NULL?
- In che modo i puntatori sono correlati agli array?
La memoria del calcolatore è divisa in Stack, dove sono immagazzinate variabili statiche, e Heap, che consente l'allocazione e de-allocazione dinamica della memoria tramite puntatori.
Per assegnare l'indirizzo di una variabile a un puntatore, si utilizza il simbolo &, ad esempio: `p_x = &x;`, dove `p_x` conterrà l'indirizzo di memoria di `x`.
È buona norma inizializzare un puntatore a NULL per evitare problemi di accesso a celle di memoria non valide, garantendo così una gestione più sicura della memoria.
I puntatori e gli array sono strettamente legati, poiché un array rappresenta l'indirizzo del primo elemento del vettore, rendendo un puntatore simile a un array, come dimostrato dall'equivalenza `f_array2 = &f_array[0];`.