Il linguaggio C è molto flessibile rispetto ad altri linguaggi: assegna la giusta quantità di memoria alle variabili. Questa caratteristica permette di creare programmi portabili che utilizzano di volta in volta i valori giusti per la piattaforma. Prima di introdurre le funzioni che gestiscono la memoria, vediamo com’è organizzata la stessa.

La memoria si divide principalmente in:

  • Stack (statica);
  • Heap (dinamica).

Nello stack vengono memorizzate le variabili. Per ogni tipo di variabile viene riservato un certo numero di byte predefinito in base all’architettura del sistema (es per le variabili di tipo int vengono riservati 4 byte), e questo valore non può essere modificato.

Quando una funzione viene invocata, vengono allocate variabili locali e parametri sullo stack, in un record di attivazione. Terminata la funzione, il record di attivazione viene cancellato, e lo stack viene riportato nello stato in cui era precedentemente.

L’ heap, al contrario è una memoria dinamica, dove il programmatore può allocare e deallocare la memoria a suo piacimento tramite le opportune funzioni calloc() e malloc() che vedremo più tardi. La gestione diretta della memoria deve essere utilizzata in maniera opportuna, infatti un’operazione compiuta in modo errato, può comportare errori difficili da individuare.

La gestione dell’ heap avviene tramite l’uso di puntatori e  le funzioni che permettono di gestirlo  sono 4:

  • Malloc() e calloc(): servono per allocare un’area di memoria;
  • Free(): dealloca o rilascia la memoria allocata;
  • Realloc(): permette di modificare un’area di memoria allocata precedentemente.

Un comando molto utilizzato è anche il sizeof() che consente di conoscere esattamente l’occupazione di tutti i tipi, e variabili, inseriti nel codice. Queste funzioni sono disponibili includendo la libreria malloc.h.

MALLOC (CALLOC)

La funzione MALLOC () ha la seguente sintassi: void* malloc (unsigned int size);

dove al posto di size specificheremo quanta memoria vogliamo allocare per la nostra variabile o per il nostro array. Essendoci all’ inizio il valore di ritorno indicato come void , ci ritornerà l’indirizzo della zona di memoria allocata. Ecco un esempio pratico:

memoria

N.B. Le funzione malloc e calloc sono simili tra loro. Di conseguenza la trattazione della funzione calloc viene omessa.

REALLOC

La funzione REALLOC () viene utilizzata per modificare un’area di memoria che è stata precedentemente utilizzata. La sintassi di questa funzione è la seguente:

void * realloc ( void * BlockAddress, size_t   NewSize );

La funzione realloc cambia la dimensione di un blocco di memoria heap precedentemente allocato con malloc, calloc o realloc il cui indirizzo iniziale è BlockAddress e lo porta a NewSize byte

Attenzione però, il nuovo indirizzo potrebbe essere diverso da BlockAddress.

Se BlockAddress è NULL e NewSize è diverso da zero, realloc è equivalente ad una malloc che alloca da zero una quantità di memoria pari a NewSize. Se non c’è memoria sufficiente per espandere il blocco della dimensione richiesta, realloc restituisce NULL e quindi il blocco non sarà modificato. Se BlockAddress è un puntatore valido e NewSize è zero, realloc libera il blocco e restituisce NULL:  in paratica si comporta come una chiamata a free(BlockAddress).

Detto ciò, vediamo un esempio pratico:

realloc

 

Nel prossimo articolo parleremo della Della gestione di una Lista, se invece ti sei perso lo scorso articolo, si è parlato dei Puntatori.

Stai cercando altre guide? Allora dai uno sguardo alla nostra raccolta dedicata alla Programmazione C.

Alla prossima!