Adesso proporremo l'uso della funzione realloc() per definire un array flessibile, ovvero un array cui viene riservata della memoria suddivisa in blocchi di dimensione arbitraria. Una volta "saturato" il primo blocco, utilizziamo realloc() per allocare il blocco successivo. La suddivisione in blocchi avviene durante la fase di lettura, che essendo, appunto, dinamica, permette di minimizzare le chiamate a realloc() e di avere un dimensionamento abbastanza preciso.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int main()
{
char buffer[20];
int i=0, n=0, x, *array, nb;
/* byte allocati */
int allocati;
/* byte in un blocco */
int dimbloc;
/* byte in un intero */
int dimint;
/* byte contenenti interi */
int usati;
nb = 1;
printf("Elementi in un blocco: %d\n", nb);
dimint = sizeof(int);
dimbloc = nb * dimint;
usati = 0;
array = (int *)malloc(dimbloc);
if(array == NULL)
{
printf("Memoria insufficiente\n");
exit(1);
}
allocati = dimbloc;
printf("Allocati: %d bytes\n", allocati);
printf("Input di interi terminati da # :\n");
while(scanf("%d", &x))
{
usati += dimint;
if(usati>allocati)
{
allocati += dimbloc;
array = (int *)realloc(array, allocati);
if(array == NULL)
{
printf("Memoria insufficiente\n");
exit(1);
}
i++;
}
/* in questo modo vengono letti n interi */
array[n++] = x;
}
printf("\n");
printf("Allocati: %d bytes\n", allocati);
printf("Dim. blocchi: %d bytes\n", dimbloc);
printf("Dim. intero: %d bytes\n", dimint);
printf("Usati: %d bytes\n", usati);
printf("Chiamate realloc: %d\n", i);
printf("Numeri: %d\n", n);
printf("\nEcco i numeri\n");
for(i=0; i<n; i++)
{
printf("%5d%c", array[i], i%10 == 9 ? '\n' : ' ');
}
printf("\n");
return 0;
}
La sintassi della funzione realloc() ha due argomenti, il primo riguarda l'indirizzo di memoria, il secondo specifica la nuova dimensione del blocco; il tipo restituito è un tipo puntatore a void, il quale nel programma è stato castato a puntatore ad intero, per verificare che il suo valore fosse NULL.
ESEMPIO PRATICO (Visualizza il sorgente completo)
Facciamo notare come, all'interno del programma, venga usata la direttiva "malloc" per allocare la giusta memoria
al puntatore. Tale comando permette, nel suo uso semplificato, di ottimizzare notevolmente il programma e di rendere
più veloce l'esecuzione. Inoltre, allocando prima la memoria, il puntatore è già pronto per contenere le informazioni,
in poche parole è stato inizializzato nel migliore dei modi.
265 /* creazione primo elemento */
266 // Alloco la memoria necessaria
267 p = (struct elemento *)malloc(sizeof(struct elemento));
268 // Metto daInserire nell'informazione del puntatore
269 p->inf = daInserire;
270 // p punta a NULL, ovvero il marcatore di fine lista
271 p->pun = NULL;
|
|