Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 31 di 47
  • livello principiante
Indice lezioni

Allocazione dinamica della Memoria (malloc)

Come è organizzata la memoria, la differenza tra heap e stack e quali sono le funzioni principali per creare e gestire array dinamici.
Come è organizzata la memoria, la differenza tra heap e stack e quali sono le funzioni principali per creare e gestire array dinamici.
Link copiato negli appunti

Il C è per natura un linguaggio molto flessibile e un esempio di questa flessibilità è dato dalla gestione della memoria. A differenza di altri linguaggi (come C++ o Java), il C permette di assegnare la giusta quantità di memoria (solo e solamente quella necessaria) alle variabili del programma. In particolare l'uso della memoria allocata dinamicamente risulta utile con gli array. Utilizzare queste caratteristiche del C permette di creare programmi altamente portabili, in quanto utilizzano di volta in volta i valori giusti per la piattaforma.

Come è organizzata la memoria in C

Una piccola nota su come è organizzata la memoria è doverosa: la memoria è divisa sostanzialmente in due parti:

Tipo di memoria Descrizione
Stack È una parte statica, che contiene tutto ciò che sappiamo sarà allocato di certo (tutto ciò che è dichiarato nel codice quindi, come una variabile int)
Heap È una parte dinamica, in cui la dimensione degli elementi può cambiare a "runtime" ovvero durante l'esecuzione del programma

Malloc e le funzioni per allocare memoria dinamicamente

Le funzioni utilizzate per gestire la memoria dinamica sono principalmente malloc() e calloc() (calloc() è stata rinominata dall'ANSI), adibite all'allocazione della memoria, free() che, come si intuisce, serve per liberare la memoria allocata, e realloc() la cui funzione è quella di permettere la modifica di uno spazio di memoria precedentemente allocato.

Un comando particolarmente utile risulta essere sizeof, che restituisce la dimensione del tipo di dato da allocare.

Per far funzionare il programma dobbiamo includere la libreria malloc.h, senza la quale queste funzioni non potrebbero fare il loro dovere. Presentiamo un esempio per chiarire meglio l'uso di queste funzioni, in particolare allocheremo la memoria per un array con malloc(), lavoreremo sull'array stesso ed, infine, libereremo la memoria con free().

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int main()
{
int numero, *array, i;
int allocati;
numero = 100;
printf("Numero di elementi dell'array: %d\n", numero);
// alloca il numero di elementi interi che ci servono (4x100)
// e opera un cast che permette alla memoria di essere
// trattata come array di int
array = (int *) malloc(sizeof(int) * numero);
if(array == NULL)
{
printf("Memoria esaurita\n");
exit(1);
}
allocati = sizeof(int) * numero;
for(i=0; i<numero; i++)
{
array[i] = i;
}
printf("Valori degli elementi\n");
for(i=0; i<numero; i++)
{
printf("%6d%c", array[i], (i%10 == 9)?'\n':' ');
}
printf("\n\nNumero elementi %d\n", numero);
printf("Dimensione elemento %d\n", sizeof(int));
printf("Bytes allocati %d\n", allocati);
free(array);
printf("\nMemoria Liberata\n");
return 0;
}

In questo programma possiamo notare l'uso della funzione malloc() che ritorna un puntatore a carattere, corrispondente al punto di inizio, in memoria, della porzione riservata della dimensione "intera" passata come argomento; se la memoria richiesta non può essere allocata, ritorna un puntatore nullo.

Nel caso citato si può notare che è stato usata la funzione sizeof per specificare il numero esatto di byte, mentre è stata usata la coercizione per convertire il tipo di dato "puntatore a carattere" a "puntatore ad int", questo per garantire che i puntatori aritmetici vengano rappresentati correttamente. Esiste, inoltre, un legame molto forte tra puntatori ed array per trattare la memoria riservata come un array, ed è per questo che in realtà la variabile "array" non è stata definita inizialmente come array, ma come puntatore ad int (vedere lezione 13).

Ti consigliamo anche