Il linguaggio C Puntatori e dintorni.

Slides:



Advertisements
Presentazioni simili
Puntatori Linguaggio C.
Advertisements

Introduzione al linguaggio C++
Puntatori e gestione dinamica della RAM
Array multidimensionali
PUNTATORI Introduzione
Informatica Generale Marzia Buscemi
Introduzione al linguaggio C Dr. Francesco Fabozzi Corso di Informatica.
Anno accademico Gli operatori e le espressioni in C.
Il linguaggio C Gli operatori e le espressioni C Language
Anno accademico Array e puntatori in C.
Algoritmi in C++ (1) da completare
INFORMATICA Strutture iterative
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Caratteri e stringhe di caratteri
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 21 Marzo 2013.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 4 Aprile 2013.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Stringhe e Puntatori Marco D. Santambrogio – Ver. aggiornata al 18 Marzo 2013.
Process synchronization
Allocazione dinamica della memoria
Laboratorio di Linguaggi lezione VI: puntatori 2/3 Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso.
Laboratorio di Linguaggi lezione III Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea.
Laboratorio di Linguaggi lezione VII: puntatori 3/3 Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso.
Laboratorio di Linguaggi P R I M O C O M P I T I N O Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese.
Laboratorio di Linguaggi lezione IV Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea in.
Laboratorio di Linguaggi lezione V: puntatori (1/3) Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso.
APPUNTI SUL LINGUAGGIO C
Array Struttura numerate di dati. Memorizzare molti dati In informatica cè spesso bisogno di memorizzare ed elaborare un insieme costituito da molti dati.
Lab. Calc. AA 2005/061 puntatori. Lab. Calc. AA 2005/062 Attributi di un oggetto nome o identificatore; tipo o classe; valore o valori; indirizzo;
1 laboratorio di calcolo II AA 2003/04 seconda settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( )
Struct, enum, Puntatori e Array dinamici
Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri per indirizzo, passaggio.
Fondamenti di Informatica A - Massimo Bertozzi TIPI DI DATO IN C++ What's in a name? That which we call a rose By any other name would smell as sweet.
Il Linguaggio C.
Algoritmi e Programmazione Avanzata
AN FI Un denominatoe comune Comandi u notazioni che esprimono azioni che, una volta eseguite, comportano una modifica permanente dello stato interno.
AN FI Array Array in Java. AN FI Array Dichiarazione di array in Java [ ]; //oppure u [] ; int a[]; int[] a; u La dimensione non è specificata.
AN Fondam98 Puntatori Azioni e procedure Assegnamenti, indirizzi e puntatori.
CODIFICA Da flow-chart a C++.
2000 Prentice Hall, Inc. All rights reserved. Capitolo 10 (Deitel) Strutture, unioni ed enumerazioni Sommario Introduzione Definire le strutture.
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
Unità Didattica 3 Linguaggio C
Fopndamenti di programmazione. 2 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe.
Ricerca sequenziale in un array di interi
Complessità di un algoritmo
Strutture dati elementari
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2006/2007 Prof.ssa Chiara Petrioli Corso di Laurea.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Puntatori e Stringhe.
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2006/2007 Prof.ssa Chiara Petrioli Corso di Laurea.
1. 2 Variabili statiche e dinamiche Un programma è un processo in esecuzione a cui il sistema operativo assegna una certa zona di memoria. Tale zona può.
1 novembre I nomi in Java F. Bombi 1 novembre 2002.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Vettori, indirizzi e puntatori Finora abbiamo usato gli indirizzi nel chiamare  la funzione scanf()  le altre funzioni per riferimento Tuttavia la vera.
Vettori (a una dimensione)
Parte 3 Lo stato: variabili, espressioni ed assegnazioni
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 11 Ottobre 2014.
Università di Torino – Facoltà di Scienze MFN Corso di Studi in Informatica Programmazione I - corso B a.a prof. Viviana Bono Blocco 7 – Array.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
1 Il linguaggio C Puntatori e dintorni. 2 Puntatori : idea di base In C è possibile conoscere e denotare l’indirizzo della cella di memoria in cui è memorizzata.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 11 Marzo 2014.
1 Il linguaggio C Precisazioni sull’esperienza in laboratorio.
Il linguaggio C Puntatori e dintorni.
1 Laboratorio di Programmazione di Sistema - C Susanna Pelagatti Ricevimento: Me ,
Lezione 9 e 10 - Segmenti di memoria e puntatori - Aritmetica dei puntatori - Formattazione dei dati - Significato ed impiego del cast - Tipi di dato strutturato.
Linguaggio C: Funzioni e Puntatori Laboratorio di Programmazione Gruppo 1.
Programmazione e Laboratorio di Programmazione
Transcript della presentazione:

Il linguaggio C Puntatori e dintorni

Puntatori : idea di base In C è possibile conoscere e denotare l’indirizzo della cella di memoria in cui è memorizzata una variabile (il puntatore) es : int a = 50; /* una var intera */ int * b; /* una var puntatore a interi */ ... b = &a; /* assegna a b l’indirizzo della cella in cui è memorizzata a */

Puntatori : idea di base (2) In C è possibile conoscere e denotare l’indirizzo della cella di memoria in cui è memorizzata una variabile (il puntatore) es : int a = 50; int *b; … b = &a; a è memorizzata nella cella 350 350 50 450 ...

Puntatori : idea di base (3) nometype * è il tipo degli indirizzi delle variabili di tipo nometype es : int a = 50; int * b; … b = &a; 350 50 450 ... b è memorizzata nella cella 450 (&b) tipo dei puntatori a intero

Puntatori : idea di base (4) Operatore & denota l’indirizzo della cella di memoria in cui è memorizzata una variabile (il puntatore) es : int a = 50; int *b; … b = &a; 350 50 450 350 Dopo questo assegnamento in b è memorizzato l’indirizzo di a

Puntatori : idea di base (5) Operatore di dereferenziazione ‘ * ’ è possibile conoscere e/o modificare il contenuto di una variabile manipolando direttemente il suo puntatore es : int a = 50; int *b = &a; … *b = *b + 4; 350 54 450 350 Dopo questo assegnamento in a è memorizzato il valore 50 + 4 Denota la variabile a indirizzo b

Puntatori : idea di base (6) NULL costante predefinita (in stdio.h) che denota il puntatore nullo È possibile definire puntatori per tutti itipi base e le strutture con (*) double *a, *b; /* ripetere ‘*’ */ int *a, b, c[4], **d; struct studente * t1; Segnaposto ( %p ) stampa il valore dell’indirizzo in notazione esadecimale

Aritmetica dei puntatori È possibile scrivere espressioni puntatore usando alcuni degli usuali operatori aritmetici (+, -, --, ++) int a[3],*p=&a[0]; …… IN+12 IN+8 IN+4 IN a[2] a[1] a[0] p contiene l’indirizzo IN

Aritmetica dei puntatori (2) È possibile scrivere espressioni puntatore usando alcuni degli usuali operatori aritmetici int a[3],*p=&a[0]; p = p+1; …… IN+12 IN+8 IN+4 IN a[2] a[1] a[0] p contiene l’indirizzo IN + 4

Aritmetica dei puntatori (3) È possibile scrivere espressioni puntatore usando alcuni degli usuali operatori aritmetici int a[3],*p=&a[0]; p = p+1; p--; …… IN+12 IN+8 IN+4 IN a[2] a[1] a[0] p contiene l’indirizzo IN

Aritmetica dei puntatori (4) È possibile scrivere espressioni puntatore usando alcuni degli usuali operatori aritmetici (+, -, --, ++) int a[3],*p=&a[0]; p = p+1; p--; p+=3; …… IN+12 IN+8 IN+4 IN a[2] a[1] a[0] p contiene l’indirizzo IN + 12 (sizeof(int)==4…..)

Aritmetica dei puntatori (5) È possibile scrivere espressioni puntatore usando alcuni degli usuali operatori aritmetici (+, -, --, ++) int a[3],*p=&a[0],*q; p = p+1; p--; q = p; p+=3; a[0] = p-q; …… IN+12 IN+8 IN+4 IN a[2] a[1] a[0] A[0] contiene 3, numero di int memorizzabili fra p e q

Puntatori e array…. Il nome di un array, è il puntatore (costante) al primo elemento dell’array int a[3],*p=&a[0],*q; q = a; …… IN+12 IN+8 IN+4 IN a[2] a[1] a[0] q contiene l’indirizzo IN a == IN

Puntatori e array…. (2) L’operatore [-] è una abbreviazione …. int a[3],*p=&a[0],*q, tmp; /* i due stm che seguono sono equivalenti */ tmp = a[2]; tmp = *(a+2); …… a+3 a+2 a+1 a a[2] a[1] a[0]

Puntatori e array…. (3) L’operatore [–] è una abbreviazione …. e può essere usato con una qualsiasi variabile puntatore int a[3],*p=a,*q, tmp; tmp = a[2]; tmp = p[2]; …… a+3 a+2 a+1 a a[2] a[1] a[0]

Puntatori e array…. (4) I seguenti frammenti di codice sono equivalenti : int a[N],*p=a,*q, tmp; int sum = 0; /* versione 1 */ for(i=0;i<N;i++) sum+= a[i]; /* versione 2 */ sum+= *(a+i);

Puntatori e array…. (5) I seguenti frammenti di codice sono equivalenti (segue) : int a[N],*p=&a[0],*q, tmp; int sum = 0; /* versione 3 */ for(i=0;i<N;i++) sum+= p[i]; /* versione 4 */ for(p=a;p<(a+N);p++) sum+= *p;

Puntatori e array…. (6) Una riflessione sulle stringhe le stringhe sono array di caratteri char a[7]=“ciao”; le stringhe costanti possono essere definite anche come const char * pp=“ciao”; char * pp=“ciao”; attenzione! Se a questo punto cercate di modificare un elemento di pp (es. pp[2]=`f`;) avete un errore a run time mentre a[2]=`f`; è completamente corretto

Passaggio di parametri per riferimento Tutti i parametri delle funzioni C sono passati per valore il loro valore viene copiato sullo stack ogni modifica al parametro nel corpo della funzione non modifica l’originale è possibile realizzare passaggi per riferimento utilizzando i puntatori i passaggi per riferimento permettono di modificare il valore di una variabile nell’ambiente del chiamante

Passaggio di parametri per riferimento (2) Esempio : la funzione che scambia fra loro i valori di due variabili : si potrebbe pensare di programmarla come ... void scambia (int x, int y){ int tmp; tmp = x; x = y; y = tmp; } e poi chiamare scambia(a,b)

Passaggio di parametri per riferimento (3) Esempio : la funzione che scambia fra loro i valori di due variabili : si potrebbe pensare di programmarla come ... void scambia (int x, int y){ int tmp; tmp = x; x = y; y = tmp; } non funziona! Perché lo scambio viene fatto sulle copie

Passaggio di parametri per riferimento (3.1) Esempio : la funzione che scambia fra loro i valori di due variabili : esempio di chiamata int a=4, b=5; scambia (a,b); stack &a &b 4 Frame chiamante 5 &x &y 4 Frame scambia 5

Passaggio di parametri per riferimento (3.2) Esempio : la funzione che scambia fra loro i valori di due variabili : alla fine dell’esecuzione di scambia (prima di ritornare al chiamante) int a=4, b=5; scambia (a,b); &a &b 4 Frame chiamante 5 &x &y 5 Frame scambia 4

Passaggio di parametri per riferimento (3.3) Esempio : la funzione che scambia fra loro i valori di due variabili : al momento di eseguire la printf() (il frame di scambia non e’ piu’ significativo) int a=4, b=5; scambia (a,b); printf(“%d,%d”,a,b); &a &b 4 Frame chiamante 5

Passaggio di parametri per riferimento (4) Esempio : la funzione che scambia fra loro i valori di due variabili : la versione corretta è ... void scambia (int* x, int* y){ int tmp; tmp = *x; *x = *y; *y = tmp; } con chiamata scambia(&a,&b)

Passaggio di parametri per riferimento (4.1) Versione corretta di scambia ... : esempio di chiamata int a=4, b=5; scambia (&a,&b); stack &a &b 4 Frame chiamante 5 Ogni modifica a *x modifica il valore di a nell’ambiente del chiamante &x &y &a Frame scambia &b

Passaggio di parametri per riferimento (3.2) Esempio : versione corretta di scambia ... alla fine dell’esecuzione di scambia (prima di ritornare al chiamante) int a=4, b=5; scambia (&a,&b); &a &b 5 Frame chiamante 4 &x &y &a Frame scambia &b

Passaggio di parametri per riferimento (3.3) Esempio : versione corretta di scambia... al momento di eseguire la printf() (il frame di scambia non e’ piu’ significativo) int a=4, b=5; scambia (&a,&b); printf(“%d,%d”,a,b); &a &b 5 Frame chiamante 4

Passaggio di parametri per riferimento (5) ATTENZIONE : gli array sono passati sempre per riferimento perchè quello che si passa è il nome dell’array void assegna (int x[]){ x[0] = 13; } con chiamata int a[10]; assegna(a); /* qua a[0] vale 13 */

Passaggio di parametri per riferimento (6) Inoltre : le due scritture void assegna (int x[]){ x[0] = 13; } e void assegna (int* x){ sono del tutto equivalenti si preferisce usare le prima per leggibilità

Passaggio di parametri per riferimento (7) Tipicamente le funzioni che lavorano su array hanno un secondo parametro che fornisce la lunghezza int somma (int x[], int l){ int i, s=0; for(i=0;i<l;i++) s += x[i]; return s; } somma tutti gli elementi di un array intero di lunghezza l

Passaggio di parametri per riferimento (8) Per gli array multidimensionali la cosa è più complessa!!!! int somma (int x[][4], int l){ int i, j, s=0; for(i=0;i<l;i++) for(j=0;j<4;j++) s += x[i][j]; return s; } invece di 4 posso usare N costante

Passaggio di parametri per riferimento (9) Perché dobbiamo specificare l’ampiezza di una seconda dimensione di un array ? Dipende dalla strategia di memorizzazione per gli array multidimensionali es: int a[2][3]={{1,2,3},{4,5,6}; a &a[0][1] &a[0][2] &a[1][0] &a[1][1] &a[1][2] 1 100 104 108 112 116 120 2 a[i][j] ha come indirizzo a+i*3+j 3 4 5 6

Passaggio di parametri per riferimento (10) Se non conosco la lunghezza della seconda dimensione il compilatore non riesce a generare codice corretto int somma (int x[][4], int l){ int i, j, s=0; for(i=0;i<l;i++) for(j=0;j<4;j++) s += x[i][j]; return s; }

Passaggio di parametri per riferimento (11) C’è un modo migliore di questo di rappresentare gli array multidimensionali in C, lo vediamo più avanti

E le strutture ??? Le strutture vengono sempre passate per valore Se una struttura contiene un array l’array viene copiato! Attenzione quando si passano strutture con grossi campi array! Se voglio modificare una struttura devo sempre utilizzare i puntatori!

E le strutture ??? (2) Es . typedef struct studente { char nom_cogn[40]; unsigned int matricola; }studente; void scambia (studente * s1, studente * s2);

E le strutture ??? (3) Es . void scambia (studente * s1, studente * s2){ … (*s1).matricola = 4; s1-> matricola = 4; /*sono equivalenti */ }

E le strutture ??? (4) Es . Come si dichiara una lista in C ? Usando i puntatori typedef struct nodo { struct nodo * next; int info; } nodo; Mi serve il nome della struttura !

Allocazione dinamica della memoria La creazione di nuove variabili a run time (tipo new()), viene effettuata in C utilizzando le funzioni di libreria standard che permettono l’allocazione dinamica di porzioni contigue di memoria malloc(), calloc(), realloc() #include <stdlib.h> es. Con queste primitive è possibile creare dinamicamente variabili e array di dimensione non nota a priori

Array dinamici -- malloc() Vediamo come creare dinamicamente un array di 10 posizioni int * a; /*conterrà il puntatore al primo elemento dell’array*/ a = malloc(10*sizeof(int)); Punta all’indirizzo iniziale della nuova area allocata 40 byte 100 96 heap

Array dinamici -- malloc() (2) Vediamo come creare dinamicamente un array di 10 posizioni int * a; /*conterrà il puntatore al primo elemento dell’array*/ a = malloc(10*sizeof(int)); if(a==NULL) printf(“fallimento!\n”); Se malloc non riesce ad allocare l’area di memoria richiesta restituisce NULL (verificare …..) heap

Array dinamici -- malloc() (3) Vediamo come creare dinamicamente un array di 10 posizioni int * a; /*conterrà il puntatore al primo elemento dell’array*/ a = malloc(10*sizeof(int)); if(a==NULL) printf(“fallimento!\n”); else { a[4] = 345; … 40 byte 100 96 heap L’array si può accedere con i consueti operatori (come se fosse statico)

Array dinamici -- malloc() (4) malloc() non inizializza la memoria a 0! Possiamo inizializzarla esplicitamente o usare calloc() int * a; /*conterrà il puntatore al primo elemento dell’array*/ a = calloc(10,sizeof(int)); if(a==NULL) printf(“fallimento!\n”); else { a[4] = 345; …

Array dinamici -- realloc() realloc() modifica la lunghezza di un’area allocata precedentemente int * a, *b; /*puntatori al primo elemento dell’array*/ a = malloc(10*sizeof(int)); …. b = realloc(a,20*sizeof(int)); /* adesso b punta ad un’array di 20 elementi */

Array dinamici -- realloc() (2) Meglio usare sempre due puntatori diversi (a,b) ! Altrimenti in caso di fallimento NULL sovrascrive il vecchio puntatore

Array dinamici -- free() Lo spazio allocato sullo heap non viene deallocato all’uscita delle funzioni La deallocazione deve essere richiesta esplicitamente usando free() int * a; a = malloc(10*sizeof(int)); …. free(a); /* se qua accedo di nuovo ad a può succedere di tutto */

tipo puntatore generico: void* non si può dereferenziare è necessario un cast prima di manipolare la variabile puntata. Es : void * c; int a; c = &a; *c = 5; /* scorretto*/ *(int *)c = 5; /* corretto*/

tipo puntatore generico: void* (2) Serve a scrivere funzioni ‘polimorfe’ in modo un po’ brutale Es : il tipo della malloc() è void * malloc (unsigned int size); quando scrivo int * a; a = malloc(10*sizeof(int)); viene effettuato un cast implicito a (int *)

tipo puntatore generico: void* (3) Tipi delle altre funzioni di allocazione e deallocazione void * calloc (unsigned int size); void * realloc (void * ptr, unsigned int size); void free (void * ptr);

I puntatori a funzione Consideriamo la funzione : int somma (int x, int y){ return x+y; } se proviamo ad eseguire printf(“%p”,somma); otteniamo un valore esadecimale che rappresenta un indirizzo legale del nostro programma ??????????????????????????

I puntatori a funzione (2) Consideriamo la funzione : int somma (int x, int y){ return x+y; } Codice compilato di somma IND somma è un puntatore costante con valore pari a IND

I puntatori a funzione (3) Consideriamo la funzione : int somma (int x, int y){ return x+y;} /* variabile di tipo funzione (int,int)->int */ int (*fun) (int,int); int a; fun = somma; a = fun(3,5);

I puntatori a funzione (4) Consideriamo la funzione : int somma (int x, int y){ return x+y;} /* variabile di tipo funzione (int,int)->int */ int (*fun) (int,int); int a; fun = somma; a = fun(3,5); Ma a che serve ????????????

I puntatori a funzione (5) Serve a definire funzioni che prendono come argomenti altre funzioni (di ordine superiore) : void map (int (*fun) (int), int x[], int l){ for(i=0;i<l;i++) x[i] = fun(x[i]); } è un iteratore che applica la funzione fun a tutti gli elementi dell’array x

I puntatori a funzione (6) Esempio di uso della map : int piu_uno (int x){ return x+1;} int quad (int x){ return x*x;} ... int a[3] = {3,4,5}; map(piu_uno,a,3); /* somma uno a tutti gli elementi */ map(quad,a,2); /* eleva al quadrato i primi due elementi */

Argomenti della linea di comando Gli argomenti della linea di comando sono accessibili all’interno della funzione main() il SO li mette sulla pila prima di attivare il processo il formato in cui sono resi disponibili è fisso int main (int argc, char* argv [] ){ …… } Array di puntatori agli argomenti (ciascuno è una stringa, tipo char*) Numero di argomenti nella linea di comando

Argomenti della linea di comando (2) Un esempio : %> a.out una stringa per a.out argv[0] a . o u t \O 5 u n a \O argc s t r i n g a \O p e r \O argv a . o u t \O

Argomenti della linea di comando (3) Es. schema di programma che stampa gli argomenti sulla linea di comando : int main (int argc, char* argv [] ){ …… for(i=0;i<argc;i++) printf(“arg %d: %s”,i,argv[i]); … … }

Array multidimensionali come array di puntatori Vogliamo permettere la definizione di funzioni su array multidimensionali che non dipendono dal valore delle dimensioni successive alla prima int sum_mat (int ** MAT, int n, int m){ … } Nome della matrice Numero di righe, colonne

Array multidimensionali come array di puntatori (2) Vogliamo accedere agli elementi dell’array usando la solita notazione [-][-] int sum_mat (int ** MAT, int n, int m){ … MAT[i][j] = …; } *(MAT + i*m + j) Il compilatore dovrebbe conoscere il legame fra questi due oggetti

Array multidimensionali come array di puntatori (3) Una alternativa: abbandonare l’allocazione contigua per righe : MAT[0] MAT MAT[2][2] 1 2 3 4 MAT[1] 3 5 7 9 MAT[2] 4 6 1 2 MAT[3] 7 2 6 2 MAT[4] 4 5 1 2

Array multidimensionali come array di puntatori (4) Una alternativa: vediamo i tipi ... int[4] MAT[0] MAT MAT[2][2] int** 1 2 3 4 MAT[1] 3 5 7 9 MAT[2] 4 6 1 2 MAT[3] int*[5] 7 2 6 2 MAT[4] 4 5 1 2

Array multidimensionali come array di puntatori (5) Una alternativa: in memoria non ho più aree contigue ... indirizzo valore 40 44 48 52 70 74 78 82 86 1 2 3 4 40 120 140 400 4 MAT[0] MAT 120 124 128 132 140 144 148 152 3 5 7 9 4 6 1 2 MAT[1] MAT[2]

Array multidimensionali come array di puntatori (6) Perché funziona? int sum_mat (int ** MAT, int n, int m){ … MAT[i][j] = …; } *(*(MAT + i) + j) Questo legame non interessa più!

Array multidimensionali come array di puntatori (7) Funzione di allocazione int** mat_new(unsigned int m, unsigned int n){ int i, ** a, errore = FALSE; a = malloc(m*sizeof(int*)); if (a==NULL) return NULL; for(i=0;(i<m)&(!errore_riga); i++){ a[i] = malloc(n*sizeof(int)); if (a[i] ==NULL) errore = TRUE; } if (errore) /* ...gestione errori */ else return a;

Array multidimensionali come array di puntatori (8) Funzione di deallocazione void mat_free(int ** a, unsigned int m) { int i; /* dealloco tutte le righe */ for(i=0;i<m; i++) free(a[i]); /* dealloco il vettore dei puntatori alle righe */ free(a); }

assert() Permettono di fare controlli di consistenza a tempo di esecuzione prevenire meglio che curare … es. un indice i e’ davvero dentro i limiti dell’array? int x, a[N], i; …… assert(i<N); x = a[i];

assert() (2) #include <assert.h> … assert(expr); se expr è falsa il sistema stampa un messaggio di errore e termina se expr è vera non ha alcun effetto!

assert() (3) Le assert costano! Quando usarle per effettuare controlli di consistenza dopo chiamate a codice complesso tipicamente non abbiamo i sorgenti (se è scritto da altri) … e comunque anche se li abbiamo non è mai garantita la correttezza! si controlla se i valori risultanti sono rispondenti alle specifiche fornite si controllano invarianti noti dell’applicazione che stiamo scrivendo