Allocazione dinamica delle variabili
Transcript
Allocazione dinamica delle variabili
Allocazione dinamica delle variabili • L'allocazione dello spazio di memoria occupato dalla variabili puo' essere effettuata durante l'esecuzione del programma. Allocazione dinamica delle variabili 1 2 Allocazione statica Allocazione dinamica Nell'allocazione statica il programmatore dichiara il tipo della variabile ed in caso di variabile vettoriale stabilisce la dimensione del vettore. Esempio int vett[5]; Nell'allocazione dinamica il programmatore dichiara il esclusivamente il tipo della variabile. L'allocazione dello spazio di memoria per contenere la variabile viene fatta durante l'esecuzione del programma. /* allocazione di un vettore di 5 interi */ Allocazione statica = allocazione effettuata all'atto della compilazione. L'accesso alle variabili dinamiche avviene attraverso il loro indirizzo. Esempio int *vett; /* allocazione di un puntatore ad una variabile di tipo intera */ 3 Allocazione 4 malloc() La creazione di una variabile dinamica avviene prelevando dalla memoria un blocco di dimensione opportuna tramite una funzione di allocazione (malloc). Funzione appartenente alla libreria alloc.h che permette di allocare memoria per le variabili dinamiche. Prototipo della funzione: void * malloc (unsigned int dimensione); • la funzione restituisce un puntatore a void (puntatore a memoria non strutturata). Per utilizzare correttamente l'area allocata occorre effettuare un'operazione di cast del puntatore verso il tipo di dato a cui l'area e' destinata • se il valore restituito dalla funzione e' NULL, l'operazione di allocazione non ha avuto successo (ad esempio per mancanza di memoria disponibile). 5 Maurizio Rebaudengo 6 1 malloc() (II) Funzionamento • Il parametro della funzione specifica la dimensione (in numero di byte) della memoria da allocare. • per scrivere codice portabile NON è opportuno utilizzare valori interi costanti come parametri della funzione malloc, ma è consigliabile utilizzare l’operatore sizeof. All’atto della chiamata della funzione di allocazione, il sistema operativo cerca nell’area di memoria libera la zona contigua di dimensione specificata dal parametro della funzione. Se l’area di memoria e’ disponibile, la funzione restituisce il puntatore all’inizio della zona di memoria allocata. Se l’area di memoria non e’ disponibile, la funzione restituisce il valore NULL. 7 … Esempio int dim; 8 Dichiarazione della variabile puntatore char *stringa; … All’atto della compilazione la variabile stringa viene allocata per memorizzare un puntatore ad una area di memoria che contiene una variabile di tipo char. dim = 50; stringa = (char *) malloc(sizeof(char) * dim); if (stringa == NULL) La variabile non viene inizializzata dunque non punta a nessuna area di memoria. { Per accedere ad un’area di memoria occorre effettuare un’allocazione dinamica attraverso la chiamata della funzione malloc(). printf(“memoria non disponibile\n”); return; } strcpy(stringa, “questa e’ una stringa”); printf(“%s\n”, stringa); … 9 10 Allocazione dinamica Deallocazione Dopo la chiamata della funzione malloc(), la variabile puntatore contiene l’indirizzo di memoria dell’area allocata. Per liberare la memoria allocata dinamicamente, si utilizza la funzione free(). stringa q u e s t a e Il blocco deallocato viene restituito all’area di memoria libera e potrà essere riutilizzato successivamente tramite eventuale chiamata a malloc. stringa[0] stringa[1] stringa[2] stringa[3] stringa[4] stringa[5] stringa[6] stringa[7] Sintassi void free (void *p) • il parametro della funzione è un puntatore ad un’area di memoria allocata tramite malloc(). 11 Maurizio Rebaudengo 12 2 Esercizio #include <stdio.h> #include <alloc.h> Si realizzi un programma in grado da leggere da file un insieme di numeri interi. void main() Il numero di interi da leggere e’ scritto nella prima riga del file. { FILE * finp; int num_data; int i; int *vettore; ... 13 14 vettore = (int *) malloc(num_data*sizeof(int)); ... if (vettore == NULL) finp = fopen("dati.dat", "r"); { if (finp == NULL) printf(“Errore in allocazione ‘vettore’\n”); { return; printf("Errore nell'apertura del file \n"); return; } for (i = 0 ; i < num_data ; i++) } fscanf(finp,"%d", &vettore[i]); else free(vettore) { fclose(finp); fscanf(finp, "%d", &num_data); } ... 15 } 16 Esercizio Soluzione Si realizzi un programma per il caricamento della classifica di un campionato di calcio. Il numero di squadre e’ memorizzato nella prima riga del file. #include <stdio.h> typedef struct { char nome_sq[30]; int punti; } classifica; 17 Maurizio Rebaudengo 18 3 main() { printf("\nIntroduci nome file: "); classifica *vett_class; scanf("%s", nomefile); char nomefile[30]; int num_squadre; num_squadre = carica_dati(nomefile, vett_class); int carica_dati( char nomefile[], classifica vett_class[]); if (num_squadre) int scrivi_dati( classifica vett_class[], { int num_squadre); scrivi_dati(vett_class, num_squadre); free(vett_class); } } /* end main */ 19 20 int carica_dati(char nomefile[], classifica vett_class[]) { int i, squadre=0, stato; FILE *filedati; for (i=0 ; i<squadre ; i++) if ( (filedati = fopen(nomefile,"r")) == NULL) fscanf(filedati,”%s %d”, vett_class[i].nome_sq, {printf("Errore apertura: %s\n", nomefile); &vett_class[i].punti); return(0): } fclose(filedati); else } { return(squadre); fscanf(filedati, “%d”, &squadre); vett_class=(classifica *)malloc(squadre*sizeof(classifica)); } if (vett_class== NULL) {printf(“Errore in allocazione\n”); return(0); } 21 void scrivi_dati(classifica num_squadre) vett_class[], 22 int Esercizio { int indice; printf("Squadra Si memorizzi una insieme di stringhe di lunghezza variabile in memoria minimizzando lo spazio di memoria utilizzato. Classifica\n"); for (indice = 0; indice < num_squadre; indice++) { Il numero di stringhe da memorizzare è scritto nella prima riga del file. printf("%-16s", vett_class[indice].nome_sq); printf(" %d\n", vett_class[indice].punti); } return; } 23 Maurizio Rebaudengo 24 4 Struttura dati #include <stdio.h> #include <alloc.h> vettore vettore[0] c a s c i vettore[1] c a s a \0 n a \0 void main() { vettore[2] vettore[3] vettore[4] FILE * finp; vettore[5] int num; vettore[6] char stringa[80]; vettore[7] int i; vettore[8] vettore[9] char ** vettore; vettore[10] ... vettore[11] vettore[12] 25 26 ... vettore=(char **)malloc(num*sizeof(char *)); finp = fopen("stringa.dat", "r"); if (vettore == NULL) if (finp == NULL) { { printf(“Errore in allocazione ‘vettore’\n”); printf("Errore nell'apertura del file\n"); return; return; } } for (i = 0 ; i < num ; i++) else { { fscanf(finp,"%s", stringa); fscanf(finp, "%d", &num); vettore[i]=(char *) ... malloc(sizeof(char)*(strlen(stringa)+1)); ... 27 28 if (vettore[i] == NULL) {printf(“Errore in ‘vettore[%d]’\n”,i); return; } strcpy(vettore[i], stringa); } for (i=0; i<num ; i++) free(vettore[i]); free(vettore) fclose(finp); } } 29 Maurizio Rebaudengo 5