Allocazione dinamica della memoria in C: malloc(), calloc()
⚡ Riepilogo intelligente
L'allocazione dinamica della memoria in C riserva e rilascia memoria heap in fase di esecuzione utilizzando le funzioni malloc(), calloc(), realloc() e free() della libreria stdlib.h, consentendo ai programmi di dimensionare array e strutture in modo flessibile quando i requisiti non sono noti prima dell'esecuzione.

Come funziona la gestione della memoria in C?
Quando si dichiara una variabile utilizzando un tipo di dati di base, il compilatore C alloca automaticamente spazio di memoria per la variabile in un pool di memoria chiamato stack.
Ad esempio, una variabile float occupa in genere 4 byte (a seconda della piattaforma) quando viene dichiarata. Possiamo verificare questa informazione utilizzando l'operatore sizeof, come mostrato nell'esempio seguente.
#include <stdio.h> int main() { float x; printf("The size of float is %d bytes", sizeof(x)); return 0;}
L'output sarà:
The size of float is 4 bytes
Inoltre, un array con una dimensione specificata viene allocato in blocchi di memoria contigui, ogni blocco ha la dimensione di un elemento:
#include <stdio.h> int main() { float arr[10]; printf("The size of the float array with 10 element is %d", sizeof(arr)); return 0;}
Il risultato è:
The size of the float array with 10 element is 40
Come appreso finora, quando si dichiara un tipo di dato di base o un array, la memoria viene gestita automaticamente. Tuttavia, in C esiste un processo di allocazione della memoria che permette di implementare un programma in cui la dimensione dell'array non viene determinata fino all'esecuzione del programma stesso (runtime). Questo processo è chiamato "allocazione dinamica della memoria".
Allocazione dinamica della memoria in C
L'allocazione dinamica della memoria (DAM) è l'allocazione e la liberazione manuale della memoria in base alle esigenze di programmazione. La memoria dinamica viene gestita e resa disponibile tramite puntatori che puntano al nuovo spazio di memoria allocato in un'area che chiamiamo heap.
Ora puoi creare e distruggere una serie di elementi dinamicamente in fase di esecuzione senza problemi. Per riassumere, la gestione automatica della memoria utilizza lo stack e l'allocazione dinamica della memoria C utilizza l'heap.
IL la libreria ha funzioni responsabili della gestione dinamica della memoria.
| Funzione | Missione |
|---|---|
| malloc () | Alloca la memoria della dimensione richiesta e restituisce il puntatore al primo byte di spazio assegnato. |
| calloc() | Alloca lo spazio per gli elementi di un array. Inizializza gli elementi a zero e restituisce un puntatore alla memoria. |
| riallocare() | Viene utilizzato per modificare la dimensione dello spazio di memoria precedentemente allocato. |
| Gratuito() | Libera o svuota lo spazio di memoria precedentemente allocato. |
Parliamo delle funzioni di cui sopra con la loro applicazione
Funzione malloc() in C
La funzione C malloc() indica l'allocazione della memoria. È una funzione che viene utilizzata per allocare dinamicamente un blocco di memoria. Riserva lo spazio di memoria della dimensione specificata e restituisce il puntatore nullo che punta alla posizione di memoria. Il puntatore restituito è solitamente di tipo void. Significa che possiamo assegnare la funzione C malloc() a qualsiasi puntatore.
Sintassi della funzione malloc():
ptr = (cast_type *) malloc (byte_size);
Qui,
- ptr è un puntatore di cast_type.
- La funzione C malloc() restituisce un puntatore alla memoria allocata di byte_size.
Esempio di malloc():
Example: ptr = (int *) malloc (50)
Quando questa istruzione viene eseguita con successo, viene riservato uno spazio di memoria di 50 byte. L'indirizzo del primo byte di spazio riservato è assegnato al puntatore ptr di tipo int.
Consideriamo un altro esempio:
#include <stdlib.h> int main(){ int *ptr; ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */ if (ptr != NULL) { *(ptr + 5) = 480; /* assign 480 to sixth integer */ printf("Value of the 6th integer is %d",*(ptr + 5)); } }
Produzione:
Value of the 6th integer is 480
- Si noti che sizeof(*ptr) è stato utilizzato al posto di sizeof(int) per rendere il codice più robusto nel caso in cui la dichiarazione di *ptr venga successivamente convertita in un tipo di dati diverso.
- L'allocazione potrebbe non riuscire se la memoria non è sufficiente. In questo caso restituisce un puntatore NULL. Quindi, dovresti includere il codice per verificare la presenza di un puntatore NULL.
- Tieni presente che la memoria allocata è contigua e può essere trattata come un array. Possiamo usare l'aritmetica dei puntatori per accedere agli elementi dell'array anziché usare le parentesi [ ]. Consigliamo di usare + per fare riferimento agli elementi dell'array perché usare l'incremento ++ o += cambia l'indirizzo memorizzato dal pointer.
La funzione Malloc() può essere utilizzata anche con il tipo di dati carattere e con tipi di dati complessi come le strutture.
funzione free() in C
La memoria per variabili viene deallocato automaticamente in fase di compilazione. Nell'allocazione dinamica della memoria, è necessario deallocare la memoria in modo esplicito. In caso contrario, potresti riscontrare un errore di memoria insufficiente.
La funzione free() viene chiamata per rilasciare/deallocare la memoria in C. Liberando la memoria nel programma, se ne rende disponibile altra per un utilizzo successivo.
Per esempio:
#include <stdio.h> int main() { int* ptr = malloc(10 * sizeof(*ptr)); if (ptr != NULL){ *(ptr + 2) = 50; printf("Value of the 2nd integer is %d",*(ptr + 2)); } free(ptr); }
Produzione:
Value of the 2nd integer is 50
funzione calloc() in C
La funzione C calloc() sta per contiguous allocation. Questa funzione è usata per allocare più blocchi di memoria. È una funzione di allocazione dinamica della memoria che è usata per allocare la memoria a strutture dati complesse come array e strutture.
La funzione Malloc() viene utilizzata per allocare un singolo blocco di spazio di memoria mentre calloc() in C viene utilizzata per allocare più blocchi di spazio di memoria. Ogni blocco allocato dalla funzione calloc() ha la stessa dimensione.
Sintassi della funzione calloc():
ptr = (cast_type *) calloc (n, size);
L'istruzione precedente viene utilizzata per allocare n blocchi di memoria della stessa dimensione.
Dopo che lo spazio di memoria è stato allocato, tutti i byte vengono inizializzati a zero.
Viene restituito il puntatore che attualmente si trova sul primo byte dello spazio di memoria allocato.
Ogni volta che si verifica un errore nell'allocazione dello spazio di memoria, ad esempio per carenza di memoria, viene restituito un puntatore nullo.
Esempio di calloc():
Il programma seguente calcola la somma di una sequenza aritmetica.
#include <stdio.h> int main() { int i, * ptr, sum = 0; ptr = calloc(10, sizeof(int)); if (ptr == NULL) { printf("Error! memory not allocated."); exit(0); } printf("Building and calculating the sequence sum of the first 10 terms \ n "); for (i = 0; i < 10; ++i) { * (ptr + i) = i; sum += * (ptr + i); } printf("Sum = %d", sum); free(ptr); return 0; }
Risultato:
Building and calculating the sequence sum of the first 10 terms
Sum = 45
calloc() vs. malloc(): differenze chiave
Di seguito è riportata la differenza fondamentale tra malloc() contro calloc() in do:
La funzione calloc() è generalmente più adatta ed efficiente di quella malloc(). Mentre entrambe le funzioni sono usate per allocare spazio di memoria, calloc() può allocare più blocchi in una sola volta. Non devi richiedere un blocco di memoria ogni volta. La funzione calloc() è usata in strutture dati complesse che richiedono più spazio di memoria.
Il blocco di memoria allocato da calloc() in C viene sempre inizializzato a zero mentre nella funzione malloc() in C contiene sempre un valore spazzatura.
funzione realloc() in C
Utilizzando la funzione realloc() del linguaggio C, è possibile aggiungere ulteriore memoria a una porzione di memoria già allocata. Questa funzione espande il blocco corrente lasciando inalterato il contenuto originale. In C, realloc() sta per "reallocazione di memoria".
realloc() può essere utilizzato anche per ridurre la dimensione della memoria precedentemente allocata.
Sintassi della funzione realloc():
ptr = realloc (ptr,newsize);
L'istruzione precedente alloca un nuovo spazio di memoria con una dimensione specificata nella variabile newsize. Dopo aver eseguito la funzione, il puntatore verrà riportato al primo byte del blocco di memoria. La nuova dimensione può essere maggiore o minore della memoria precedente. Non possiamo essere sicuri che il blocco appena allocato punterà alla stessa posizione di quella del blocco di memoria precedente. Questa funzione copierà tutti i dati precedenti nella nuova regione. Garantisce che i dati rimangano al sicuro.
Esempio di realloc():
#include <stdio.h> int main () { char *ptr; ptr = (char *) malloc(10); strcpy(ptr, "Programming"); printf(" %s, Address = %u\n", ptr, ptr); ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size strcat(ptr, " In 'C'"); printf(" %s, Address = %u\n", ptr, ptr); free(ptr); return 0; }
Ogni volta che realloc() in C risulta in un'operazione non riuscita, restituisce un puntatore null e anche i dati precedenti vengono liberati.
Array dinamici in C
Un array dinamico in C consente al numero di elementi di crescere secondo necessità. Gli array dinamici C sono ampiamente utilizzati negli algoritmi informatici.
Nel programma seguente, abbiamo creato e ridimensionato un array dinamico in C
#include <stdio.h> int main() { int * arr_dynamic = NULL; int elements = 2, i; arr_dynamic = calloc(elements, sizeof(int)); //Array with 2 integer blocks for (i = 0; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); elements = 4; arr_dynamic = realloc(arr_dynamic, elements * sizeof(int)); //reallocate 4 elements printf("After realloc\n"); for (i = 2; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); free(arr_dynamic); }
Risultato del programma C Dynamic array sullo schermo:
arr_dynamic[0]=0 arr_dynamic[1]=1 After realloc arr_dynamic[0]=0 arr_dynamic[1]=1 arr_dynamic[2]=2 arr_dynamic[3]=3

