Fondamenti di Informatica I a.a Il linguaggio C Utilizzo avanzato di array e puntatori Gli array multidimensionali Gli array di puntatori I puntatori a puntatori Le classi di memorizzazione Durata fissa e durata automatica Lambito di visibilità C L a n g u a g e
Fondamenti di Informatica I a.a Utilizzo avanzato di array e puntatori
Fondamenti di Informatica I a.a array multidimensionale Un array di array è un array multidimensionale e viene dichiarato per mezzo di una sequenza di coppie di parentesi quadre Anche se un array multidimensionale viene memorizzato come una sequenza di elementi, può essere manipolato come un array di array Per accedere ad un elemento di un array multidimensionale occorre specificare tanti indici quante sono le dimensioni dellarray Gli array multidimesionali 1 /* x è un array di tre elementi costituiti * da array di cinque elementi */ int x[3][5];
Fondamenti di Informatica I a.a Gli array multidimensionali sono memorizzati con precedenza delle righe, cioè lultimo indice varia più velocemente Esempio Esempio: int ar[2][3] { {0,1,2}, {3,4,5} }; Gli array multidimensionali C ar[1][0] ar[1][1] ar[1][2] ar[0][0] ar[0][1] ar[0][2] Nellinizializzazione, ogni riga di valori è racchiusa fra parentesi graffe (in questo caso, servono per migliorare la leggibilità)
Fondamenti di Informatica I a.a Laccesso allelemento ar[1][2] viene interpretato come *(ar[1] 2), ovvero *(*(ar 1) 2) Poiché ar è un array di array, viene effettuato un doppio scaling: …quando si valuta *(ar 1), 1 rappresenta un array di tre interi (12 byte sulla macchina di riferimento) …quando si valuta *(*(ar 1) 2), 2 rappresenta 2 interi (8 byte) complessivamente si ha uno spostamento di 20 byte rispetto allindirizzo base (si ottiene lindirizzo esadecimale 1014) Se vengono specificati meno indici rispetto alle dimensioni, il risultato è un puntatore al tipo base dellarray; per esempio… ar[1] è equivalente a &ar[1][0] puntatore adint e fornisce come risultato un puntatore ad int Lo standard ANSI non impone limiti al numero di dimensioni degli array; è comunque richiesto di gestire almeno array a sei dimensioni Gli array multidimensionali 3
Fondamenti di Informatica I a.a Linizializzazione di array multidimensionali 1 In fase di inizializzazione di un array multidimensionale, occorre specificare ogni riga tra parentesi graffe static Se i valori iniziali non sono sufficienti, ed il vettore è static, gli elementi mancanti vengono inizializzati a zero Esempio Esempio: static int examp[5][3] { {1,2,3}, {4}, {4}, {5,6,7} {5,6,7} }; }; In modo analogo al caso dei vettori, se viene parzialmente omessa la dichiarazione della dimensione di un array multidimensionale, il compilatore la calcola sulla base del numero dei valori iniziali specificati ) (
Fondamenti di Informatica I a.a Nel caso degli array multidimensionali, infatti, può essere omessa la dimensione dellarray più esterno, mentre è obbligatorio specificare le altre Esempio Esempio: static int a_ar[][2] {{1,1},{0,0},{1,2}}; produce un array di dimensione 3 2, perché sono presenti 6 valori iniziali Esempio Esempio: static int b_ar[][] {{1,2,3},{4,5,6}}; /* SCORRETTO */ Non si può determinare se larray è 3 2 o 2 3 (il raggruppamento dei dati di inizializzazione non è sufficiente!): specificare la seconda dimensione avrebbe risolto ogni ambiguità Linizializzazione di array multidimensionali 2
Fondamenti di Informatica I a.a Per passare un array multidimensionale come argomento di funzione è sufficiente specificarne il nome: il valore passato è un puntatore allelemento iniziale dellarray che è ancora un array Nella funzione chiamata, largomento deve essere dichiarato in modo appropriato È possibile omettere la dimensione dellarray che viene passato, ma è necessario specificare la dimensione di ogni elemento dellarray Array multidimensionali come argomenti di funzione 1 void f2(received_arg) int received_arg[][6]; { … … … } int f1() { static int ar[5][6]; … … … f2(ar); … … … } int (*received_arg)[6];
Fondamenti di Informatica I a.a Una modalità alternativa consiste nel passare esplicitamente un puntatore al primo elemento e la dimensione dellarray Il vantaggio di questo approccio è la flessibilità: non occorre conoscere a priori la dimensione degli elementi dellarray; occorre però calcolare manualmente laritmetica degli indici: received_arg[x][y] è memorizzato allindirizzo received_arg x dim2 y received_arg x dim2 y Array multidimensionali come argomenti di funzione 2 int f1() { static int ar[5][6]; … … … f2(ar,5,6); … … … } void f2(received_arg,dim1,dim2) int **received_arg; int dim1,dim2; { … … … } int È un puntatore a un puntatore a int
Fondamenti di Informatica I a.a Esempio array multidimensionali 1 Scrivere una funzione che determina il tipo del risultato di unespressione binaria in base ai tipi degli operandi La funzione riceve due argomenti interi che rappresentano i tipi degli operandi e fornisce un intero che rappresenta il tipo del risultato include typedef enum {SPECIAL 2, ILLEGAL, INT, FLOAT, DOUBLE, POINTER, LAST} TYPES; TYPES type_needed(type1,type2) TYPES type1, type2; { static TYPES result_type[LAST][LAST] { /* int float double pointer */ /*int*/ INT, FLOAT, DOUBLE, POINTER, /*float*/ FLOAT, FLOAT, DOUBLE, ILLEGAL, /*double*/ DOUBLE, DOUBLE, DOUBLE, ILLEGAL, /*pointer*/ POINTER, ILLEGAL, ILLEGAL, SPECIAL }; TYPES result result_type[type1][type2]; if (result ILLEGAL) printf(Operazione scorretta su puntatori\n); return result; }
Fondamenti di Informatica I a.a Esempio array multidimensionali 2 result_type La parte principale del programma è costituita dalla dichiarazione ed inizializzazione dellarray result_type: enum Ogni tipo di dati viene fatto corrispondere ad un valore intero per mezzo della dichiarazione enum In base alle modalità di definizione dellarray bidimensionale, i due valori di ingresso sono indici, che individuano univocamente lelemento dellarray corrispondente al tipo del risultato enum La dichiarazione enum assicura che ogni costante venga associata ad un unico valore intero e che LAST rappresenti il numero totale di tipi (viene usato nella dichiarazione dellarray)
Fondamenti di Informatica I a.a Esempio array multidimensionali 3 La stessa dichiarazione (almeno per il compilatore) avrebbe potuto essere scritta per mezzo di interi char result_type[4][4] {0,1,2,3,1,1,2, 1,2,2,2, 1,3, 1, 1, 2}; diminuendo sensibilmente la comprensibilità e la mantenibilità del programma SPECIAL int Nel caso SPECIAL, loperazione è corretta solo se i puntatori riferiscono oggetti dello stesso tipo e loperatore è il segno meno: il risultato è un int
Fondamenti di Informatica I a.a Errori di accesso ad array multidimensionali ar[1,2] 0; /* Lecito, ma probabilmente scorretto */ ar[1][2] 0; /* Corretto */ Nella prima istruzione… espressione1 espressione2 …la virgola viene interpretata come operatore, si valuta quindi espressione1, che vale 1 ed il cui risultato non viene utilizzato, e, successivamente, espressione2, che vale 2 (le due espressioni sono costanti) …si ottiene laccesso ad ar[2] arintar[2]puntatore ad int Se ar è un array bidimensionale di int, ar[2] è un puntatore ad int (costante) Viene segnalato un errore di incompatibilità di tipo: fuorviante dato che la causa dellerrore è luso della virgola
Fondamenti di Informatica I a.a Gli array di puntatori 1 Si consideri la dichiarazione: char *ar_of_p[5]; ar_of_p non La variabile ar_of_p è un array di cinque elementi di tipo puntatore e non un puntatore ad un array di cinque elementi Loperatore di accesso allelemento di un array [] ha precedenza superiore alloperatore di accesso allindirizzo contenuto in un puntatore I puntatori non sono stati inizializzati, per cui puntano a posizioni di memoria qualsiasi
Fondamenti di Informatica I a.a Gli array di puntatori 2 Esempio Esempio: char *ar_of_p[5]; char c0 = a; char c1 = b; ar_of_p[0] = &c0; ar_of_p[1] = &c1; ar_of_p[0] ar_of_p[1] ar_of_p[2] ar_of_p[3] C non definito ar_of_p[4] 1000 c c0 1FFF b a
Fondamenti di Informatica I a.a Esempio array di puntatori 1 array di puntatori Gli array di puntatori vengono usati per gestire array di stringhe Esempio Esempio: Realizzare una funzione che, dato un intero compreso fra 1 e 12, in ingresso, stampa il nome del mese corrispondente include char *month_text(m) int m; { static char *month[13] {Badmonth, January, February, March, April, May, June, July, August, September, October, November, December }; if (m>12) { printf(Valore scorretto); exit(1); } return month[m]; }
Fondamenti di Informatica I a.a Esempio array di puntatori 2 monthchar La variabile month è un array di puntatori a char costituito da 13 elementi: come conseguenza dellinizializzazione, ogni puntatore fa riferimento allelemento iniziale di una stringa La motivazione delluso di un puntatore aggiuntivo con un valore inutile consiste nel non voler effettuare sottrazioni dallindice: è comune non utilizzare lelemento iniziale di un array quando il valore dellindice comincia logicamente da 1 Non definendo Badmonth, si dovrebbe cambiare listruzione di ritorno al chiamante in return month[m 1];
Fondamenti di Informatica I a.a Esempio array di puntatori 3 Nota Nota : I caratteri che costituiscono una stringa devono essere consecutivi Le stringhe corrispondenti ai nomi dei mesi vengono memorizzate dal compilatore in qualunque posizione libera della memoria A 300F A A month[0] month[1] month[2] month[3] month[4] month[5] month[6] month[7] month[8] month[9] month[10] month[11] month[12] C C C 1030 B a d m o n t h \0 J a n u a r y F e b r u a r y M a r c h A 200B 200C 200D 200E 200F
Fondamenti di Informatica I a.a I puntatori a puntatori 1 puntatori a puntatori I puntatori a puntatori sono costrutti usati in programmi sofisticati: per dichiarare un puntatore a puntatore occorre far precedere il nome della variabile da due asterischi consecutivi int **p; int dichiara p come puntatore ad un puntatore ad int int Per accedere al valore dellint, è necessario utilizzare i doppi asterischi: j **p; assegna un intero a j
Fondamenti di Informatica I a.a I puntatori a puntatori 2 Esempio Esempio: int r 5; int *q &r; int *q &r; int **p &q; int **p &q; È possibile assegnare valori ad r come: r 10; /* Assegnamento diretto */ *q 10; /* Assegnamento con un livello di indirezione */ *q 10; /* Assegnamento con un livello di indirezione */ **p 10; /* Assegnamento con due livelli di indirezione */ **p 10; /* Assegnamento con due livelli di indirezione */ 4 byte r q p C 100C 99C 1004
Fondamenti di Informatica I a.a Esempio: Prodotto matrice vettore /* Funzione per il calcolo di A b, con… ** A: matrice m n di float (in input) ** b: vettore di dimensione n di float (in input) ** m, n: interi, numero di righe e colonne di A (in input) ** x: vettore di float di dimensione m, risultato (in output) */ float *prod_mv(a, b, m, n, x) float a[][100], b[], x[]; /* ma, nella funzione, sono puntatori */ int m, n; { int i, j; for (i 0; i m; i ) { x[i] 0.0; for (j 0; j n; j ) x[i] a[i][j] b[j]; } return x; }
Fondamenti di Informatica I a.a Le classi di memorizzazione
Fondamenti di Informatica I a.a Introduzione 1 ambito di visibilitàscope Nel linguaggio C, viene offerta la possibilità di condividere variabili e di delimitare le porzioni di codice che sfruttano tali condivisioni, mediante la definizione dellambito di visibilità, o scope, delle variabili ambito di visibilità Lambito di visibilità è il termine tecnico che denota la parte del testo sorgente C in cui è attiva la dichiarazione di un nome durata Inoltre, le variabili hanno una durata, che descrive il lasso temporale di memorizzazione dei valori di una variabile: durata fissa Nel caso di variabili con durata fissa, i valori memorizzati vengono mantenuti anche allesterno dellambito di visibilità classe di memorizzazione Le proprietà di visibilità e di durata individuano la classe di memorizzazione di una variabile
Fondamenti di Informatica I a.a Introduzione 2 jdurata automaticaardurata fissa static La variabile j ha durata automatica, mentre ar ha durata fissa, perché dichiarata static: j A j viene automaticamente allocata memoria ogni volta che viene eseguito il blocco che la contiene (può avere indirizzi diversi per esecuzioni diverse del blocco di codice) ar ar viene allocato la prima volta che viene eseguito il blocco e mantiene lindirizzo originale per lintera esecuzione del programma void func() { int j; static int ar[] {1,2,3,4} … … … } jar visibilità a livello di blocco func Le variabili j ed ar hanno entrambe visibilità a livello di blocco, perché definite allinterno di un blocco: possono essere referenziate solo dalle istruzioni che appartengono al blocco (il corpo della funzione func) jarlocali Le variabili j ed ar sono dette locali Esempio
Fondamenti di Informatica I a.a Durata fissa e durata automatica durata fissa durata automatica Le variabili con durata fissa sono permanenti, mentre le variabili con durata automatica sono allocate più volte durante lesecuzione del programma Ad una variabile fissa viene associata una locazione di memoria allinizio del programma, che non cambia fino al termine dello stesso Ad una variabile automatica viene allocata memoria ogni volta che si entra nel suo ambito di visibilità; se il codice che appartiene allambito di visibilità della variabile viene rieseguito, la variabile viene generalmente allocata altrove: non si mantiene il valore della variabile fra due esecuzioni successive static Le variabili locali sono automatiche per default, ma possono essere rese fisse se dichiarate static auto La parola chiave auto definisce esplicitamente una variabile automatica, ma è usata raramente perché ridondante
Fondamenti di Informatica I a.a Linizializzazione delle variabili 1 void increment() { int j 1; static int k 1; j ; k ; printf(j: %d\t k: %d\n, j, k); } main() { increment(); } increment() jk La funzione increment() incrementa i valori delle variabili j e k, entrambe inizializzate a 1 Il risultato dellesecuzione del programma è: j: 2k: 2 j: 2k: 3 j: 2k: 4 Le variabili fisse vengono inizializzate una sola volta, mentre quelle automatiche vengono inizializzate ogni volta che viene eseguito il blocco che le contiene
Fondamenti di Informatica I a.a Linizializzazione delle variabili 2 stack Le variabili fisse vengono inizializzate di default al valore zero, quelle automatiche non vengono inizializzate (e sono normalmente allocate sullo stack) Le variabili scalari automatiche possono essere inizializzate con una qualunque espressione, con il solo vincolo che tutte le variabili contenute nellespressione siano state dichiarate (e inizializzate) in precedenza Le variabili con durata fissa possono essere inizializzate solo per mezzo di espressioni costanti, ossia non contenenti nomi di variabili
Fondamenti di Informatica I a.a Luso di variabili con durata fissa Le variabili con durata fissa sono comunemente impiegate per tenere traccia del numero di volte che una funzione viene eseguita e per modificarne il comportamento ad intervalli regolari page_type chap_title La variabile page_type agisce da elemento di controllo: quando il numero della pagina è dispari, la funzione stampa la stringa puntata da chap_title sul lato destro della pagina; se il numero della pagina è pari, la stringa appare spostata a sinistra page_type page_type deve essere fissa, altrimenti si stamperebbe sempre lintestazione relativa alle pagine dispari #define ODD 0 #define EVEN 1 void print_header(chap_title) char *chap_title; { static char page_type ODD; if (page_type ODD) { printf(\t\t\t\t\t%s\n\n, chap_title); page_type EVEN; } else { printf(%s\n\n, chap_title); page_type ODD; }
Fondamenti di Informatica I a.a Lambito di visibilità 1 ambito di visibilità Lambito di visibilità di una variabile definisce la regione di codice da cui è possibile accedere alla variabile programmafile funzioneblocco Esistono quattro tipi di ambiti di visibilità: programma, file, funzione e blocco ambito di visibilità a livello di programma variabili globali Lambito di visibilità a livello di programma implica che una variabile è accessibile da tutti i file sorgente; le variabili con ambito di visibilità a livello di programma sono variabili globali ambito di visibilità a livello di file Lambito di visibilità a livello di file implica che una variabile è accessibile dal punto in cui è dichiarata fino alla fine del file sorgente in cui si trova ambito di visibilità a livello di funzione Lambito di visibilità a livello di funzione implica che il nome di una variabile è accessibile dallinizio alla fine della funzione in cui è dichiarata ambito di visibilità a livello di blocco Lambito di visibilità a livello di blocco implica che una variabile è accessibile dal punto in cui è dichiarata fino alla fine del blocco in cui si trova
Fondamenti di Informatica I a.a Lambito di visibilità 2 Le variabili dichiarate allinterno di un blocco hanno ambito di visibilità a livello di blocco static Le variabili dichiarate allesterno di un blocco hanno ambito di visibilità a livello di file se sono static, oppure a livello di programma goto Solo le etichette dellistruzione goto hanno ambito di visibilità a livello di funzione Lambito di visibilità di una variabile è determinato dalla posizione della dichiarazione: Ambito di visibilità a livello di blocco Ambito di visibilità a livello di programma Ambito di visibilità a livello di file Ambito di visibilità a livello di funzione Le relazioni gerarchiche tra gli ambiti di visibilità
Fondamenti di Informatica I a.a Esempio Esempio: I parametri delle funzioni hanno ambito di visibilità a livello di blocco: sono trattati come se fossero la prima dichiarazione di variabile nel blocco di livello più alto contenuto nella funzione Lambito di visibilità 3 int i; /* ambito di visibilità a livello di programma */ static int j; /* ambito di visibilità a livello di file */ int func(k) /* ambito di visibilità a livello di programma */ int k; /* ambito di visibilità a livello di blocco */ { int m; /* ambito di visibilità a livello di blocco */ start: ; /* ambito di visibilità a livello di funzione */ … … … }
Fondamenti di Informatica I a.a Lambito di visibilità 4 Il C consente lattribuzione dello stesso nome a variabili diverse con ambiti di visibilità distinti È anche possibile che variabili con lo stesso nome abbiano ambiti parzialmente intersecati: la variabile con lambito di visibilità più limitato preclude temporaneamente la visibilità dellaltra int j 10; /* ambito di visibilità a livello di programma */ main() { int j; /* ambito di visibilità a livello di blocco: nasconde la variabile globale j */ for (j 0; j<5; j ) printf(j: %d, j); } Lesecuzione del programma produce: j: 0 j: 1 j: 2 j: 3 j: 4 La variabile globale j mantiene inalterato il valore iniziale 10
Fondamenti di Informatica I a.a Lambito di visibilità a livello di blocco e funzione Una variabile con ambito di visibilità a livello di blocco non può essere acceduta dallesterno del blocco in cui è dichiarata consente di proteggere la variabile da effetti collaterali non desiderati riduce la complessità del programma, rendendolo più leggibile e mantenibile Variabili possono essere dichiarate allinterno di blocchi innestati, nascondendo temporaneamente le variabili con lo stesso nome eventualmente definite in blocchi più esterni goto Le etichette dellistruzione goto sono gli unici nomi con ambito di visibilità a livello di funzione: devono avere nomi univoci allinterno della stessa funzione, mentre nomi coincidenti in funzioni diverse non originano conflitti
Fondamenti di Informatica I a.a Lambito di visibilità a livello di file e programma Associare un ambito di visibilità a livello di file a una variabile significa renderla referenziabile nella parte rimanente del file in cui è definita Se il file contiene più funzioni, tutte le funzioni che seguono la dichiarazione della variabile sono in grado di referenziarla static Per dichiarare una variabile con ambito di visibilità a livello di file occorre inserire la dichiarazione al di fuori delle funzioni e usare la parola chiave static variabili globali Le variabili con ambito di visibilità a livello di programma, dette variabili globali, sono visibili in tutti i file sorgente (compreso quello in cui vengono dichiarate) static Una variabile globale deve essere dichiarata al di fuori delle funzioni e non usando la parola chiave static
Fondamenti di Informatica I a.a I due significati di static static Allinterno di un blocco, static attribuisce ad una variabile durata fissa, anziché automatica static Allesterno di una funzione, static non è correlata alla durata della variabile, ma ne controlla lambito di visibilità a livello di file, anziché di programma static La parola chiave static specifica sia lambito di visibilità che la durata di una variabile: Allinterno di un blocco, le regole di visibilità del blocco sono più stringenti di quelle a livello di file: la durata fissa è lunico effetto che si manifesta Allesterno di una funzione, la durata è già fissa: lambito di visibilità a livello di file è lunico effetto che si manifesta
Fondamenti di Informatica I a.a Le variabili globali variabili globali Luso delle variabili globali dovrebbe essere evitato perché aumenta la complessità dei programmi e li rende difficilmente mantenibili Le variabili globali possono portare a conflitti tra moduli se, per errore, vengono scelti nomi uguali per variabili globali distinte Quando occorre condividere dati tra procedure diverse, è buona regola passare i dati come parametri o passare puntatori allarea di memoria condivisa linkerbinder Le regole di attribuzione di nomi alle variabili globali sono diverse: i nomi globali devono essere riconoscibili non solo al compilatore, ma anche al linker ed al binder : lo standard ANSI garantisce il riconoscimento dei primi sei caratteri (tuttavia, nulla vieta di aggiungere caratteri per rendere i nomi più significativi)
Fondamenti di Informatica I a.a definizione Finora, la dichiarazione di variabile corrispondeva allallocazione di memoria per quella variabile: lallocazione di memoria è, in realtà, il risultato di un solo tipo di dichiarazione, detta definizione allusione Le variabili globali consentono un secondo tipo di dichiarazione, detta allusione: non si alloca memoria, ma si informa il compilatore che esiste una variabile del tipo specificato definita altrove Le variabili globali seguono le stesse regole delle funzioni: ogni volta che si utilizzano variabili definite in altro file, è necessario dichiararle con allusioni Definizioni e allusioni 1 main() { extern int f(); /* allusione a funzione */ extern int j; /* allusione a variabile */ extern float f_array_of_f[]; /* allusione a variabile */ … … …
Fondamenti di Informatica I a.a extern La parola chiave extern specifica che la variabile è definita altrove Le allusioni consentono al compilatore di effettuare i controlli di tipo: per ogni variabile globale, possono essere presenti un numero qualunque di allusioni, ma una sola definizione extern Lo standard ANSI prevede che, per definire una variabile globale, sia necessario inserire allesterno di una funzione una dichiarazione con inizializzazione: la presenza o meno della parola chiave extern non ha alcun effetto extern, definizione di prova Se il valore iniziale fosse stato omesso, il compilatore avrebbe prodotto unallusione, se è specificato extern, o una definizione di prova, che si trasforma… …in una definizione effettiva, con inizializzazione a 0, se nel file non compare altra dichiarazione …in unallusione, se nel file sorgente è contenuta una definizione reale Definizioni e allusioni 2
Fondamenti di Informatica I a.a register La parola chiave register consente di suggerire al compilatore quali variabili dovrebbero essere memorizzate nei registri register register Il livello di supporto offerto dai compilatori allo specificatore register è molto variabile: alcuni compilatori memorizzano effettivamente tutte le variabili register in registri, fino a quando ce ne sono disponibili, altri lo ignorano, altri lo interpretano per determinare se è davvero proficuo memorizzare una data variabile in un registro register register Ad una variabile register non è assegnato alcun indirizzo di memoria: anche se il suggerimento register non viene seguito dal compilatore, se si tenta di accedere allindirizzo della variabile, si ottiene una segnalazione di errore register for Sono candidati ideali per la memorizzazione register i contatori dei cicli for, sui quali vengono effettuate molte operazioni, temporalmente vicine Lo specificatore register
Fondamenti di Informatica I a.a Il modificatore di classe const const La parola chiave const (derivata dal C ) indica che una variabile non può essere modificata dopo linizializzazione: const #define La parola chiave const può essere impiegata in alternativa alla direttiva #define const char str[9] Costante; str[0] a; /* non ammesso */
Fondamenti di Informatica I a.a Riepilogo delle classi di memorizzazione Specificatore di classe di memorizzazione Allesterno di una funzione Allinterno di una funzione Argomenti di una funzione auto register auto o registerNON PERMESSOVisibilità: blocco Durata: automatica Visibilità: blocco Durata: automatica staticVisibilità: file Durata: fissa Visibilità: blocco Durata: fissa NON PERMESSO externVisibilità: programma Durata: fissa Visibilità: blocco Durata: fissa NON PERMESSO nessuno specificatore di classe Visibilità: programma Durata: fissa Visibilità: blocco Durata: automatica Visibilità: blocco Durata: automatica Posizione della dichiarazione La semantica degli specificatori di classe di memorizzazione
Fondamenti di Informatica I a.a Alle variabili con durata fissa viene riservata memoria per lintera durata del programma, mentre alle variabili con durata automatica la memoria viene allocata ogni volta che si esegue il blocco relativo: in entrambi i casi si suppone di conoscere la quantità di memoria da allocare nel momento i cui si scrive il codice sorgente talvolta loccupazione di memoria dipende strettamente dai dati in ingresso Tuttavia, talvolta loccupazione di memoria dipende strettamente dai dati in ingresso allocazione dinamica della memoria In C, esistono quattro funzioni della libreria di run time (stdlib.h) che permettono lallocazione dinamica della memoria malloc() malloc() alloca un numero specificato di byte in memoria e restituisce un puntatore allinizio del blocco allocato calloc()malloc() calloc() come malloc(), ma inizializza a zero i byte allocati; consente di allocare la memoria per più di un oggetto alla volta realloc() realloc() cambia la dimensione di un blocco precedentemente allocato free()malloc()calloc() realloc() free() libera la memoria che era stata allocata con malloc(), calloc() o realloc() Lallocazione dinamica della memoria 1
Fondamenti di Informatica I a.a malloc() Largomento di malloc() è la dimensione in byte del blocco da allocare calloc() Usando calloc(), listruzione di allocazione della memoria sarebbe list = (int *) calloc(sort_num, sizeof(int)); calloc() La funzione calloc() accetta due argomenti: il primo è il numero di oggetti a cui riservare memoria, il secondo è la dimensione di ciascun oggetto malloc()calloc() Le funzioni malloc() e calloc() memorizzano gli elementi in modo contiguo in un singolo blocco Lallocazione dinamica della memoria 2 include main() { extern void bubble_sort(); int *list, j, sort_num; printf(Numero dei valori da introdurre:); scanf(%d, &sort_num); list (int *) malloc(sort_num sizeof(int)); for (j 0; j<sort_num; j ) scanf(%d, list j); bubble_sort(list, sort_num); exit(0); } Esempio Esempio: