Nessun titolo diapositiva

Download Report

Transcript Nessun titolo diapositiva

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 L’ambito di visibilità

Fondamenti di Informatica I  a.a. 2008-09 1

Utilizzo avanzato di array e puntatori

Fondamenti di Informatica I  a.a. 2008-09 2

Gli array multidimesionali

1

Un array di array è un quadre array multidimensionale e viene dichiarato per mezzo di una sequenza di coppie di parentesi /* x è un array di tre elementi costituiti * da array di cinque elementi */ int x[3][5]; 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 dell’array Fondamenti di Informatica I  a.a. 2008-09 3

Gli array multidimensionali

2

Gli array multidimensionali sono memorizzati con precedenza delle righe, cioè l’ultimo indice varia più velocemente Esempio : int ar[2][3]  { {0,1,2}, }; {3,4,5} 1000 1004 1008

0 1 2

ar[0][0] ar[1][0] 100C 1010 1014

3 4 5

ar[0][1] ar[0][2] ar[1][1] ar[1][2] 1018 Nell’inizializzazione, ogni riga di valori è racchiusa fra parentesi graffe (in questo caso, servono per migliorare la leggibilità) Fondamenti di Informatica I  a.a. 2008-09 4

Gli array multidimensionali

3

L’accesso all’elemento 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  …quando si valuta *(*(ar 1), “1” rappresenta un array di tre interi (12 byte sulla macchina di riferimento)  1)  2), “2” rappresenta 2 interi (8 byte)  complessivamente si ha uno spostamento di 20 byte rispetto all’indirizzo base (si ottiene l’indirizzo esadecimale 1014) Se vengono specificati meno indici rispetto alle dimensioni, il risultato è un puntatore al tipo base dell’array; per esempio… ar[1] è equivalente a &ar[1][0] 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 Fondamenti di Informatica I  a.a. 2008-09 5

L’inizializzazione di array multidimensionali

1

In fase di inizializzazione di un array multidimensionale, occorre specificare ogni riga tra parentesi graffe Se i valori iniziali non sono sufficienti, ed il vettore è static, gli elementi mancanti vengono inizializzati a zero Esempio : static int examp[5][3]  { {1,2,3}, }; {4}, {5,6,7}

(

1 2 3 4 0 0 5 6 7 0 0 0 0 0 0

)

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. 2008-09 6

L’inizializzazione di array multidimensionali

2

Nel caso degli array multidimensionali, infatti, può essere omessa la dimensione dell’array più esterno, mentre è obbligatorio specificare le altre 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 : static int b_ar[][]  {{1,2,3},{4,5,6}}; /* SCORRETTO */ Non si può determinare se l’array è 3  2 o 2  3 (il raggruppamento dei risolto ogni ambiguità dati di inizializzazione non è sufficiente!): specificare la seconda dimensione avrebbe Fondamenti di Informatica I  a.a. 2008-09 7

Array multidimensionali come argomenti di funzione

1

Per passare un array multidimensionale come argomento di funzione è sufficiente specificarne il nome: il valore passato è un puntatore all’elemento iniziale dell’array che è ancora un array Nella funzione chiamata, l’argomento deve essere dichiarato in modo appropriato int f1() { static int ar[5][6]; … … … f2(ar); … … … } void f2(received_arg) int received_arg[][6]; { … … … } int (*received_arg)[6]; È possibile omettere la dimensione dell’array che viene passato, ma è necessario specificare la dimensione di ogni elemento dell’array Fondamenti di Informatica I  a.a. 2008-09 8

Array multidimensionali come argomenti di funzione

2

Una modalità alternativa consiste nel passare esplicitamente un puntatore al primo elemento e la dimensione dell’array int f1() { static int ar[5][6]; … … … f2(ar,5,6); … … … } void f2(received_arg,dim1,dim2) int **received_arg; int dim1,dim2; { … … … } È un puntatore a un puntatore a int Il vantaggio di questo approccio è la flessibilità: non occorre conoscere a priori la dimensione degli elementi dell’array; occorre però calcolare manualmente l’aritmetica degli indici: received_arg[x][y] è memorizzato all’indirizzo received_arg  x  dim2  y Fondamenti di Informatica I  a.a. 2008-09 9

Esempio array multidimensionali

1

Scrivere una funzione che determina il tipo del risultato di un’espressione binaria in base ai tipi degli operandi  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. 2008-09 */ La funzione riceve due argomenti interi che rappresentano i tipi degli operandi e fornisce un intero che rappresenta il tipo del risultato 10

Esempio array multidimensionali

2

La parte principale del programma è costituita dalla dichiarazione ed inizializzazione dell’array result_type: Ogni tipo di dati viene fatto corrispondere ad un valore intero per mezzo della dichiarazione enum In base alle modalità di definizione dell’array bidimensionale, i due valori di ingresso sono indici, che individuano univocamente l’elemento dell’array corrispondente al tipo del risultato 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 dell’array) Fondamenti di Informatica I  a.a. 2008-09 11

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 Nel caso SPECIAL, l’operazione è corretta solo se i puntatori riferiscono oggetti dello stesso tipo e l’operatore è il segno meno: il risultato è un int 12 Fondamenti di Informatica I  a.a. 2008-09

Errori di accesso ad array multidimensionali

ar[1,2]  ar[1][2]  0; /* Lecito, ma probabilmente scorretto */ 0; /* Corretto */  Nella prima istruzione… …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 l’accesso ad ar[2] 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 dell’errore è l’uso della virgola 13 Fondamenti di Informatica I  a.a. 2008-09

Gli array di puntatori

1

Si consideri la dichiarazione: char *ar_of_p[5]; La variabile ar_of_p è un array di cinque elementi di tipo puntatore e non un puntatore ad un array di cinque elementi L’operatore di accesso all’elemento di un array “[]” ha precedenza superiore all’operatore di accesso all’indirizzo contenuto in un puntatore I puntatori non sono stati inizializzati, per cui puntano a posizioni di memoria qualsiasi Fondamenti di Informatica I  a.a. 2008-09 14

Gli array di puntatori

2

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] ar_of_p[4] 2000 2001 non definito non definito non definito 996 1000 1004 1008 100C 1010 1014 c0 c1 a b 1FFF 2000 2001 2002 15 Fondamenti di Informatica I  a.a. 2008-09

Esempio array di puntatori

1

Gli array di puntatori vengono usati per gestire array di stringhe Esempio : Realizzare una funzione che, dato un intero compreso fra 1 e 12, in ingresso, stampa il nome del mese corrispondente  include  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. 2008-09 16

Esempio array di puntatori

2

La variabile month è un array di puntatori a char costituito da 13 elementi: come conseguenza dell’inizializzazione, ogni puntatore fa riferimento all’elemento iniziale di una stringa La motivazione dell’uso di un puntatore aggiuntivo con un valore inutile consiste nel non voler effettuare sottrazioni dall’indice: è comune non utilizzare l’elemento iniziale di un array quando il valore dell’indice comincia logicamente da 1 Non definendo “Badmonth”, si dovrebbe cambiare l’istruzione di ritorno al chiamante in return month[m  1]; Fondamenti di Informatica I  a.a. 2008-09 17

Esempio array di puntatori

3

Nota : I caratteri che costituiscono una stringa devono essere consecutivi Le stringhe corrispondenti ai nomi dei della memoria mesi vengono memorizzate dal compilatore in qualunque posizione libera 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] 2000 2009 2011 2500 2800 3000 3006 300A 300F 4000 400A 4011 401A 1000 1004 1008 100C 1010 1014 1018 101C 1020 1024 1028 102C 1030 ‘a’ ‘n’ ‘u’ ‘a’ ‘r’ ‘y’ ‘\0’ ‘B’ ‘a’ ‘d’ ‘m’ ‘o’ ‘n’ ‘t’ ‘h’ ‘\0’ ‘J’ 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 200A 200B 200C 200D 200E 200F 2010 ‘a’ ‘r’ ‘y’ ‘\0’ ‘F’ ‘e’ ‘b’ ‘r’ ‘u’ 2011 2012 2013 2014 2015 2016 2017 2018 2019 ‘M’ ‘a’ ‘r’ ‘c’ ‘h’ ‘\0’ 2500 2501 2502 2503 2504 2505 Fondamenti di Informatica I  a.a. 2008-09 18

I puntatori a puntatori

1

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; dichiara p come puntatore ad un puntatore ad int Per accedere al valore dell’int, è necessario utilizzare i doppi asterischi: j  **p; assegna un intero a j Fondamenti di Informatica I  a.a. 2008-09 19

I puntatori a puntatori

2

Esempio : int r  5; int *q  int **p  &r; &q;

r q p

4 byte

5 99C 1004

È possibile assegnare valori ad r come: r  10; /* Assegnamento diretto */ *q  10; /* Assegnamento con un livello di indirezione */ **p  10; /* Assegnamento con due livelli di indirezione */ 99C 1004 100C Fondamenti di Informatica I  a.a. 2008-09 20

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] } return x;  a[i][j]  b[j]; }  a.a. 2008-09 21

Le classi di memorizzazione

Fondamenti di Informatica I  a.a. 2008-09 22

Introduzione

1

Nel linguaggio C, viene offerta la possibilità di condividere variabili e di delimitare le porzioni di codice che sfruttano tali condivisioni, mediante la definizione dell’ ambito di visibilità , o

scope

, delle variabili

L’ambito di visibilità è il termine tecnico che denota la parte del testo sorgente C in cui è attiva la dichiarazione di un nome

Inoltre, le variabili hanno una temporale di memorizzazione dei valori di una variabile: Nel caso di variabili con durata , che descrive il lasso durata fissa , i valori memorizzati vengono mantenuti anche all’esterno dell’ambito di visibilità Le proprietà di visibilità e di durata individuano la memorizzazione di una variabile classe di Fondamenti di Informatica I  a.a. 2008-09 23

Introduzione

2

Esempio void func() { int j; static int ar[]  … … … } {1,2,3,4} Le variabili j ed ar hanno entrambe visibilità a livello di blocco , perché definite all’interno di un blocco: possono essere referenziate solo dalle istruzioni che appartengono al blocco (il corpo della funzione func ) Le variabili j ed ar sono dette locali La variabile j ha perché dichiarata durata automatica , mentre ar ha static : durata fissa 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 viene allocato la prima volta che viene eseguito il blocco e mantiene l’indirizzo originale per l’intera esecuzione del programma , Fondamenti di Informatica I  a.a. 2008-09 24

Durata fissa e durata automatica

Le variabili con variabili con durata fissa sono permanenti, mentre le durata automatica sono allocate più volte durante l’esecuzione del programma Ad una variabile fissa viene associata una locazione di memoria all’inizio 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 all’ambito di visibilità della variabile viene rieseguito, la variabile viene generalmente allocata altrove: non si mantiene il valore della variabile fra due esecuzioni successive Le variabili locali sono automatiche per default, ma possono essere rese fisse se dichiarate static La parola chiave auto definisce esplicitamente una variabile automatica, ma è usata raramente perché ridondante Fondamenti di Informatica I  a.a. 2008-09 25

L’inizializzazione delle variabili

1

Le variabili fisse vengono inizializzate una sola volta, mentre quelle automatiche vengono inizializzate ogni volta che viene eseguito il blocco che le contiene void increment() { int j  1; static int k  1; j  ; k  ; printf(“j: %d\t k: %d\n”, j, k); } main() { increment(); increment(); increment(); } La funzione increment() incrementa i valori delle variabili j e k, entrambe inizializzate a 1 Il risultato programma è: dell’esecuzione del j: 2 j: 2 j: 2 k: 2 k: 3 k: 4 Fondamenti di Informatica I  a.a. 2008-09 26

L’inizializzazione delle variabili

2

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 nell’espressione 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. 2008-09 27

L’uso 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 #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. 2008-09 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 deve essere fissa, altrimenti si stamperebbe sempre l’intestazione relativa alle pagine dispari 28

L’ambito di visibilità

1

L’ ambito di visibilità di una variabile definisce la regione di codice da cui è possibile accedere alla variabile Esistono quattro tipi di ambiti di visibilità: programma , file , funzione e blocco L’ ambito di visibilità a livello di programma variabile è accessibile da tutti i file sorgente; le variabili con ambito di visibilità a livello di programma sono implica che una variabili globali L’ L’ L’ ambito di visibilità a livello di file accessibile dal punto in cui è dichiarata fino alla fine del file sorgente in cui si trova ambito di visibilità a livello di funzione una variabile è accessibile dall’inizio alla fine della funzione in cui è dichiarata ambito di visibilità a livello di blocco è accessibile dal punto in cui è dichiarata fino alla fine del blocco in cui si trova implica che una variabile è implica che il nome di implica che una variabile Fondamenti di Informatica I  a.a. 2008-09 29

L’ambito di visibilità

2

L’ambito di visibilità di una variabile è determinato dalla posizione della dichiarazione: Le variabili dichiarate all’interno di un blocco hanno ambito di visibilità a livello di blocco Le variabili dichiarate all’esterno di un blocco hanno ambito di visibilità a livello di file se sono static , oppure a livello di programma Solo le etichette dell’istruzione goto hanno ambito di visibilità a livello di funzione

Ambito di visibilità a livello di programma Ambito di visibilità a livello di file Ambito di visibilità a livello di funzione Ambito di visibilità a livello di blocco

Le relazioni gerarchiche tra gli ambiti di visibilità Fondamenti di Informatica I  a.a. 2008-09 30

L’ambito di visibilità

3

Esempio : 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 */ … … … } 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 Fondamenti di Informatica I  a.a. 2008-09 31

L’ambito di visibilità

4

Il C consente l’attribuzione 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 l’ambito di visibilità più limitato preclude temporaneamente la visibilità dell’altra int j  10; /* ambito di visibilità a livello di programma */ L’esecuzione del programma produce: j: 0 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); } j: 1 j: 2 j: 3 j: 4 La variabile globale mantiene inalterato il valore iniziale 10 j Fondamenti di Informatica I  a.a. 2008-09 32

L’ambito di visibilità a livello di blocco e funzione

Una variabile con ambito di visibilità a livello di blocco non può essere acceduta dall’esterno 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 all’interno di blocchi innestati, nascondendo temporaneamente le variabili con lo stesso nome eventualmente definite in blocchi più esterni Le etichette dell’istruzione goto sono gli unici nomi con ambito di visibilità a livello di funzione: devono avere nomi univoci all’interno della stessa funzione, mentre nomi coincidenti in funzioni diverse non originano conflitti Fondamenti di Informatica I  a.a. 2008-09 33

L’ambito 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 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 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) Una variabile globale deve essere dichiarata al di fuori delle funzioni e non usando la parola chiave static Fondamenti di Informatica I  a.a. 2008-09 34

I due significati di

static

All’interno di un blocco, static attribuisce ad una variabile durata fissa, anziché automatica All’esterno di una funzione, static non è correlata alla durata della variabile, ma ne controlla l’ambito di visibilità a livello di file, anziché di programma  La parola chiave static la durata di una variabile: All’interno di un blocco, le regole di visibilità del blocco sono più stringenti di quelle a livello di file: la durata fissa è l’unico effetto che si manifesta specifica sia l’ambito di visibilità che All’esterno di una funzione, la durata è già fissa: l’ambito di visibilità a livello di file è l’unico effetto che si manifesta Fondamenti di Informatica I  a.a. 2008-09 35

Le variabili globali

L’uso 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 all’area di memoria condivisa 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. 2008-09 36

Definizioni e allusioni

1

Finora, la dichiarazione all’allocazione di memoria per quella variabile: l’allocazione di memoria è, in realtà, il risultato di un solo tipo di dichiarazione, detta dichiarazione, detta definizione Le variabili globali consentono un secondo tipo di allusione informa il compilatore che esiste una variabile del tipo specificato definita altrove di variabile corrispondeva : non si alloca memoria, ma si main() { extern int f(); /* allusione a funzione */ extern int j; /* allusione a variabile */ extern float f_array_of_f[]; /* allusione a variabile */ … … … Le variabili globali seguono le stesse regole delle funzioni: ogni volta che si utilizzano variabili definite in altro file, è necessario dichiararle con allusioni Fondamenti di Informatica I  a.a. 2008-09 37

Definizioni e allusioni

2

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 Lo standard ANSI prevede che, per definire una variabile globale, sia necessario inserire all’esterno di una funzione una dichiarazione con inizializzazione: la presenza o meno della parola chiave extern non ha alcun effetto Se il valore iniziale fosse stato omesso, il compilatore avrebbe prodotto un’allusione, se è specificato extern, o una definizione di prova definizione reale , che si trasforma… …in una definizione effettiva, con inizializzazione a 0, se nel file non compare altra dichiarazione …in un’allusione, se nel file sorgente è contenuta una Fondamenti di Informatica I  a.a. 2008-09 38

Lo specificatore

register

La parola chiave register consente di suggerire al compilatore quali variabili dovrebbero essere memorizzate nei registri 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 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 all’indirizzo della variabile, si ottiene una segnalazione di errore Sono candidati ideali per la memorizzazione register i contatori dei cicli for, sui quali vengono effettuate molte operazioni, temporalmente vicine Fondamenti di Informatica I  a.a. 2008-09 39

Il modificatore di classe

const

La parola chiave const (derivata dal C  ) indica che una variabile non può essere modificata dopo l’inizializzazione: const char str[9]  str[0]  “Costante”; ‘a’; /* non ammesso */ La parola chiave const può essere impiegata in alternativa alla direttiva #define Fondamenti di Informatica I  a.a. 2008-09 40

Riepilogo delle classi di memorizzazione

La semantica degli specificatori di classe di memorizzazione

Specificatore di classe di memorizzazione auto

o

register static extern

nessuno specificatore di classe

All’esterno di una funzione NON PERMESSO Posizione della dichiarazione Visibilità: file Durata: fissa Visibilità: programma Durata: fissa All’interno di una funzione Visibilità: blocco Durata: automatica Visibilità: blocco Durata: fissa Visibilità: blocco Durata: fissa Argomenti di una funzione Visibilità: blocco Durata: automatica NON PERMESSO NON PERMESSO Visibilità: programma Durata: fissa Visibilità: blocco Durata: automatica Visibilità: blocco Durata: automatica

41 Fondamenti di Informatica I  a.a. 2008-09

L’allocazione dinamica della memoria

1

Alle variabili con durata fissa viene riservata memoria per l’intera 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 Tuttavia, talvolta l’occupazione di memoria dipende strettamente dai dati in ingresso In C, esistono quattro funzioni della libreria di run  time (stdlib.h) che permettono l’ allocazione dinamica della memoria malloc() calloc() realloc()   alloca un numero specificato di byte in memoria e restituisce un puntatore all’inizio del blocco allocato come malloc(), ma inizializza a zero i byte allocati; consente di allocare la memoria per più di un oggetto alla volta  cambia la dimensione di un blocco precedentemente allocato free()  libera la memoria che era stata allocata con malloc(), calloc() o realloc() Fondamenti di Informatica I  a.a. 2008-09 42

L’allocazione dinamica della memoria

2

Esempio :  include  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