10 aprile 2025
Le strutture sono molto utili per definire… strutture dati.
Per esempio si possono definire array dinamici, liste concatenate, alberi, pile, code…
Gli array in C sono molto limitati, infatti dobbiamo gestire la loro lunghezza a mano…
Si può creare una struttura che contenga un array e la sua lunghezza:
Adesso si può passare la struttura come argomento di una funzione:
void stampa_array(IntArray a) {
for (int i = 0; i < a.length; i++) {
printf("%d ", a.array[i]);
}
printf("\n");
}Si nota subito che non abbiamo più bisogno di passare la lunghezza dell’array come argomento.
int append(IntArray *a, int value) {
if (a->length < MAX) {
a->array[a->length] = value;
a->length++;
return 0;
}
return 1;
}append prende come argomento un puntatore a IntArray e un intero da aggiungere all’array, l’array è passato by reference perché i suoi campi vengono modificati->, che è una forma abbreviata di (*p).membroPer esercizio si implementino le funzioni:
int get(IntArray a, int index) che restituisce l’elemento in posizione index, int insert(IntArray *a, int index, int value) che inserisce l’elemento value in posizione index, int remove(IntArray *a, int index) che rimuove l’elemento in posizione index.
Scarica il main dell’esercizio
Consiglio
Si noti che le funzioni insert e remove possono fallire se l’array è pieno o vuoto, rispettivamente, inoltre è necessario spostare tutti gli elementi dell’array.
L’implementazione che abbiamo visto ha due grossi problemi:
IntArray funziona solo con array di interi, per fare array di float, char, ecc. bisogna creare ogni volta una nuova strutturaLe strutture dati in C hanno dimensione fissa. Infatti gli array vengono inizializzati con un valore costante.
Esistono però dei comandi che permettono di allocare dinamicamente zone di memoria, permettendo di fare strutture che crescono o si rimpiccioliscono durante l’esecuzione del programma.
Le operazioni per gestire la memoria dinamica si trovano nella libreria stdlib.h e sono:
malloc (memory allocation): alloca una zona di memoria di una certa dimensionecalloc (clear allocation): alloca una zona di memoria di una certa dimensione e la inizializza a 0realloc (reallocate): cambia la dimensione di una zona di memoria già allocatamalloc, calloc e realloc restituiscono un puntatore a void, che è un puntatore generico.
Questo puntatore non fa riferimento a un certo tipo di dato, ma solo a un indirizzo di memoria.
mallocvoid* malloc(size_t size);
Supponendo di voler creare un array di interi di dimensione variabile, c’è bisogno di creare un puntatore ad interi e poi assegnargli l’indirizzo della nuova zona di memoria:
La funzione malloc accetta come argomento il numero di byte da allocare. L’esempio crea 10 cellette di memoria, ciascuna grande quanto un intero (4 byte).
callocvoid* calloc(size_t num, size_t size);
L’effetto di questo codice è lo stesso del precedente (con la malloc), ma con tutti i membri dell’array inizializzati a 0.
reallocvoid* realloc(void* ptr, size_t size);
Questa funzione cambia la dimensione di uno spazio allocato dinamicamente.
L’argomento ptr deve essere un puntatore ottenuto da una funzione ..alloc, altrimenti porta a comportamento non definito.
I dati già presenti nella zona di memoria vengono mantenuti.
Quando si usa la memoria dinamica, è importante controllare che l’allocazione sia andata a buon fine.
Se malloc, calloc o realloc non riescono a trovare spazio in memoria, restituiscono NULL.
NULL è una costante che rappresenta un puntatore all’indirizzo 0x0. NULL è definito in stdlib.h.
malloc, calloc, reallocfreevoid free(void* ptr);
ptr dopo l’esecuzione di free continua a puntare alla stessa zona di memoria, ma il contenuto di quella zona non è più garantito, si chiama dangling pointerptr il valore NULL (oppure una nuova memoria)Un array dinamico è un array la cui dimensione può cambiare durante l’esecuzione del programma.
Per implementare un array dinamico si può usare una struttura che contiene un puntatore all’array e la sua lunghezza:
ArrayListIl nuovo tipo ArrayList ha tre membri:
array è un puntatore ad interi, che punta all’array dinamicocapacity è la dimensione massima dell’arraylength è il numero di elementi attualmente presenti nell’arrayQuando length raggiunge capacity, bisogna riallocare la memoria per l’array, aumentando la sua dimensione.
L’implementazione classica della lista concatenata in C è:
Dato il file con il main e i prototipi delle funzioni, implementare:

Dati e Algoritmi