DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
Puntatori
Marco D. Santambrogio – [email protected]
Ver. aggiornata al 11 Marzo 2014
Immagini
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
Struttura dati:
typedef struct{
int R;
int G;
int B;
} pixel
pixel img[30][24];
Ma quanto è grossa immagine?
pixel=(int*3)
img= pixel*30*24
1 immagine= 2160 interi
2
Manipoliamo immagine
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
• Problema: mettiamo a 0, tutti i pixel con
rosso minore di 50 (soglia)
void TagliaRossi(pixel immagine[30][24], int soglia);
• Se volessimo scrivere una funzione che
risolve il problema dato?
 Cosa ritorna?
• NB: una immagine è un insieme di pixel, non
un solo dato!
 Quali sono i parametri di ingresso?
3
RICORDIAMO: passaggio per valore
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
Ambiente della funzione
somma
d1, d2
}
Quando invoco la funzione
in d1 e d2 vengono copiati i
valori di valore1 e valore 2
/* nel main */
float valore1, valore2;
float risultato;
risultato=somma(valore1,valore2);
valore1,
valore2
risultato
Quando la funzione
termina il valore di risultato
in somma viene
copiato il risultato nel main
risultato
Ambiente della funzione
main
4
Quindi….
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
void TagliaRossi(pixel immagine[30][24], int soglia);
/* nel main */
pixel img[30][24];
int val_soglia;
Ambiente della funzione TagliaRossi
immagine[30][24]
soglia
img[30][24]
val_soglia
TagliaRossi(img[30][24], val_soglia);
Quando invoco la funzione in
immagine[30][24] vengono copiati i
valori di img[30][24]
Perchè?
•Spreco di memoria: 2160 interi *2
•array1=array2 : VIETATO in C
Ambiente della funzione main
5
Cosa ci piacerebbe?
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
• Avere una sola copia del dato
 Non vogliamo sprecare spazio
• Poter accedere a quella copia in
maniera sicura
 Non vogliamo usare variabili globali!
Sarebbe troppo alto il rischio di
commettere errori!
Invece che per copia, ci piacerebbe
accedere tramite indirizzo
6
E quindi (veramente)…
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
Sapendo dove si trova il primo punto
aka: indirizzo primo pixel
img[0][0]
pixel img[30][24];
Con le dimensione della matrice:
Righe: 30
Colonne: 24
Possiamo arrivare ad ogni punto (r,c)!!!
Indirizzo di img[0][0] + r*Colonne + c
&img[0][0] + r*Colonne + c
7
Obiettivi
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
• Puntatori
8
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
9
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
10
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;
11
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
12
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
13
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
14
Pointer Fun with Binky
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
This is document 104 in the Stanford CS Education Library. Please see http://cslibrary.stanford.edu/ for this and other free
educational materials. Copyright Nick Parlante 1999.
15
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
16
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
17
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
18
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)
19
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)
20
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)
21
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)
22
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
23
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)
24
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)
25
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)
26
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)
27
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)
28
scanf: stringhe Vs char
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
29
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)!!
30
Somma degli elementi di un array di int
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
31
Somma degli elementi di un array di int:
funzioni
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
32
Somma degli elementi di un array di int:
funzioni – con int *valori
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE
33
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]
34
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
35
Scarica

PPT - V1