DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – [email protected] Ver. aggiornata al 11 Ottobre 2014 Obiettivi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • Puntatori 2 Variabili e indirizzi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE 3 int var; &var 2 var 1 0 • Supponiamo che la dichiarazione riservi la zona di memoria all’indirizzo 1 • var indica il contenuto della cella di memoria • &var indica l’indirizzo della cella di memoria 3 Puntatori – premessa DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • Dichiarare una variabile significa riservare una zona di memoria composta da diverse celle Il numero di celle dipende dal tipo di dato • Ogni cella di memoria ha un indirizzo fisico e: il nome della variabile indica il contenuto della cella di memoria l’operatore & permette di ottenere l’indirizzo di memoria della cella associata alla variabile cui l’operatore è applicato 4 Puntatore DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • È un tipo di dato che ammette tra i suoi valori un indirizzo di memoria La zona di memoria viene detta “puntata” dalla variabile puntatore La variabile puntatore viene detto che “punta” ad una cella di memoria • Quando dichiaro un puntatore si deve anche specificare che tipo di dato viene ospitato nella cella puntata Sintassi: int *p; 5 Significato DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE 3 int *p; &p 2 p 1 0 • p è una variabile come tutte le altre quindi p indica il contenuto della cella di memoria &p indica l’indirizzo di memoria • Quello che caratterizza una variabile di tipo puntatore è il fatto che il suo valore è esso stesso un indirizzo di memoria 6 Deferenziazione DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • Ad una variabile di tipo puntatore posso applicare l’operatore di deferenziazione * • *p indica il contenuto della cella puntata da p • Se p è un puntatore ad un intero allora *p è una semplice variabile intera int *p; *p=5; /* OK. *p è un intero */ p=5; /* errore. p è un puntatore */ • Attenzione! Il simbolo * lo uso sia nella dichiarazione che nella deferenziazione 7 Operazioni DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • A una variabile di tipo puntatore posso assegnare un indirizzo di memoria int x; int *p; &p 3 &x 2 x=5; p=&x; /* *p vale 5 */ 1 1 5 p x 0 • p punterà alla zona di memoria in cui è memorizzato il valore di x • Ad una variabile puntatore non viene mai assegnato una costante 8 Passaggio per INDIRIZZO DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • All’atto della chiamata l’indirizzo dei parametri attuali viene associato ai parametri formali il parametro attuale e il parametro formale si riferiscono alla stessa cella di memoria • Il sottoprogramma in esecuzione lavora nel suo ambiente sui parametri formali (e di conseguenza anche sui parametri attuali) ogni modifica sul parametro formale è una modifica del corrispondente parametro attuale • Gli effetti del sottoprogramma si manifestano nel chiamante con modifiche al suo ambiente locale di esecuzione 9 Passaggio parametri per indirizzo DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • Si utilizza: il costruttore di tipo puntatore per la definizione dei parametri formali della funzione float circonferenza(float *raggio) l’operatore di dereferenziazione all’interno della funzione circ = *raggio * 3.14; alla chiamata della funzione, si passa un indirizzo di variabile come parametro attuale c=circonferenza(&r); • Attenzione! Gli array sono SEMPRE passati per indirizzo. Una variabile di tipo array, infatti, è per definizione un puntatore 10 Esempio: passaggio per indirizzo DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE float circonferenza(float *raggio) { Ambiente della funzione float circ; circonferenza circ = *raggio * 3.14; *raggio = 7; /*istruzione senza circ raggio senso, voglio solo vedere cosa succede modificando il valore di un paramentro formale*/ return circ; Quando la funzione Quando invoco la funzione } /* nel main */ float c,r=5; c=circonferenza(&r); /*attenzione! D’ora in poi r vale 7 */ in raggio viene copiato l’indirizzo di r. Quindi *raggio e r sono la stessa cosa r termina il valore di circ in circonferenza viene copiato in c nel main c Ambiente della funzione main 11 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int p, int q) { int temp; a temp = p; 3 p = q; b 7 q = temp; } p 3 q 7 temp • Nel main: swap(a,b) 12 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int p, int q) { int temp; a temp = p; 3 p = q; b 7 q = temp; } p 3 q 7 temp 3 • Nel main: swap(a,b) 13 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int p, int q) { int temp; a temp = p; 3 p = q; b 7 q = temp; } p 7 q 7 temp 3 • Nel main: swap(a,b) 14 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int p, int q) { int temp; a temp = p; 3 p = q; b 7 q = temp; } p 7 q 3 temp 3 • Nel main: swap(a,b) 15 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int p, int q) { int temp; a temp = p; 3 p = q; b 7 q = temp; } Al termine dell’esecuzione di swap le variabili nel • Nel main: swap(a,b) main restano inalterate! p 7 q 3 temp 3 16 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int *p, int *q){ int temp; a temp = *p; 3 *p = *q; b 7 *q = temp; } p q temp • Nel main: swap(&a, &b) 17 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int *p, int *q){ int temp; a temp = *p; 3 b *p = *q; 7 *q = temp; } p q temp 3 • Nel main: swap(&a, &b) 18 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int *p, int *q){ int temp; a temp = *p; 7 *p = *q; b 7 *q = temp; } p q temp 3 • Nel main: swap(&a, &b) 19 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int *p, int *q){ int temp; a temp = *p; 7 *p = *q; b 3 *q = temp; } p q temp 3 • Nel main: swap(&a, &b) 20 Esempio: scambio di 2 valori interi DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE void swap (int *p, int *q){ int temp; a temp = *p; 7 *p = *q; b 3 *q = temp; } Al termine dell’esecuzione di swap le variabili nel • Nel main: swap(&a, main vengono modificate p q temp 3 &b) 21 scanf: stringhe Vs char DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE 22 Parametri di tipo array DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • Per usare in una funzione una variabile di tipo array occorre passare il suo indirizzo di base, perciò di fatto l’array è passato per locazione (indirizzo) • Una funzione C non restituirà un array (come contenuto), ma solo un puntatore a un array (cioè il suo nome come suo indirizzo)!! 23 Somma degli elementi di un array di int DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE 24 Somma degli elementi di un array di int: funzioni DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE 25 Somma degli elementi di un array di int: funzioni – con int *valori DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE 26 Parametri di tipo array DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • Due testate equivalenti: double mul(double *a, int n) double mul(double a[], int n) • N.B.: non c’è la dimensione, e n è la porzione occupata dell'array • Supponiamo di avere un array V[50]. Possibili chiamate: mul(V,50) restituisce V[0]*V[1]*…V[49] mul(V,30) restituisce V[0]*V[1]*…V[29] mul(&V[5],7) restituisce V[5]*V[6]*…V[11] mul(V+5,7) restituisce V[5]*V[6]*…V[11] 27 Fonti per lo studio + Credits DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE • Fonti per lo studio Binky Pointer Fun Video: http://cslibrary.stanford.edu/104/ • Credits Gianluca Palermo 28