Università dell’Insubria
Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese
Corso di Laurea in Informatica
Anno Accademico 2004/05
Laboratorio di Linguaggi
lezione III
Marco Tarini
Laboratorio di Linguaggi
• docente: Marco Tarini
e-mail: [email protected]
• ricevimento: Martedì 14:30 - 17:30
o anche su appuntamento
• libro di testo consigliato:
Kelley Al, Pohl Ira:
"C Didattica e Programmazione" ("A Book on C")
quarta edizione - anche la terza va bene
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Puntatori: intro
• Una tipo variabile che contiene
un indirizzo di una locazione di memoria:
– l'indirizzo di un'altra variabile!
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Puntatori: sintassi della dichiarazione
int* pippo;
" pippo " è una var di tipo int*,
cioè di tipo "puntatore ad intero"
o se preferite:
int *pippo;
" *pippo "
(cioè il valore puntato da pippo)
è una espressione di tipo "intero"
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Puntatori: sintassi dell'uso
pippo
*pippo
il valore del puntatore.
il valore dell'oggetto puntato.
entrambi possono essere sia letti che assegnati
(possono comparire da entrambi i lati di un assegnamento)
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Puntatori: preambolo
Cosa succede normalmente…
int pippo;
Inoltre, riserva quei
quattro byte per la
variabile pippo.
variabile
pippo
tipo locazione
Inoltre
int 0x612A22C
m e m o r i a
Ad esempio, la
locazione 0x612A22C
0x00000000
spazio degli indirizzi logici
il compilatore assegna
alla variabile pippo
una locazione di memoria.
0x612A0214 00 00 00 FF
0x612A0218 01 22 00 AB
0x612A021C 21 2A 02 2C
0x612A0220 12 23 D2 FF
0x612A0224 FF 02 41 A4
0x612A0228 21 00 00 00
0x612A022C 00 00 00 00
0x612A0230 12 33 A3 D0
0xFFFFFFFF
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Puntatori: significato
variabile
int* pippo;
pippo
m e m o r i a
indirizzo
tipo
int*
locazione
0x612A22C
0x612A0214 00 00 00 FF
0x612A0218 01 22 00 AB
0x612A021C 00 00 00 A0
*pippo
0x612A0220 12 23 D2 FF
0x612A0224 FF 02 41 A4
0x612A0228 21 00 00 00
0x612A022C 61 2A 02 1C
pippo
0x612A0230 12 33 A3 D0
pippo
*pippo
(il puntatore stesso) vale... 0x612A021C
(la variabile puntata da pippo) vale... 0x000000A0
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Cambiare il valore del puntatore
variabile
pippo++;
pippo
m e m o r i a
indirizzo
tipo
int*
locazione
0x612A22C
0x612A0214 00 00 00 FF
0x612A0218 01 22 00 AB
0x612A021C 00 00 00 A0
*pippo
0x612A0220 12 23 D2 FF
0x612A0224 FF 02 41 A4
0x612A0228 21 00 00 00
pippo
1C
0x612A022C 61 2A 02 20
0x612A0230 12 33 A3 D0
pippo
*pippo
+4
(il puntatore stesso) vale... 0x612A021C
(la variabile puntata da pippo) vale... 0x000000A0
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Cambiare il valore del puntatore
variabile
pippo++;
pippo
m e m o r i a
indirizzo
tipo
int*
locazione
0x612A22C
0x612A0214 00 00 00 FF
0x612A0218 01 22 00 AB
0x612A021C 00 00 00 A0
0x612A0220 12 23 D2 FF
*pippo
0x612A0224 FF 02 41 A4
0x612A0228 21 00 00 00
1C
0x612A022C 61 2A 02 20
pippo
0x612A0230 12 33 A3 D0
pippo
*pippo
(il puntatore stesso) vale... 0x612A021C 0x612A0220
(la variabile puntata da pippo) vale... 0x000000A0 0x1223D2FF
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Cambiare il valore del valore puntato
variabile
*pippo = 0x00AABB00;
pippo
m e m o r i a
indirizzo
tipo
int*
locazione
0x612A22C
0x612A0214 00 00 00 FF
0x612A0218 01 22 00 AB
0x612A021C 00 00 00 A0
12 AA
23 BB
D2 00
FF
0x612A0220 00
*pippo
0x612A0224 FF 02 41 A4
0x612A0228 21 00 00 00
0x612A022C 61 2A 02 20
pippo
0x612A0230 12 33 A3 D0
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Considerazione sull'efficienza
I
è una costante intera
i
è una variabile intera
del compilatore
int x;
...
(vale 10)
ip è un puntatore ad un intero
tabella dei Simboli
const int I=10;
int i;
int* ip;
ide.
tipo
I
i
ip
x
int
int
int*
int
locazione o valore
--0xAA000000
10
---
0xBB000000
---
0xCC000000
---
x = I;
compilazione
STORE
10
0xCC000000
x = i;
compilazione
READ
STORE
TEMP
TEMP
0xAA000000
0xCC000000
x = *ip;
compilazione
READ
READ
STORE
TEMP0
TEMP1
TEMP1
0xBB000000
TEMP0
0xCC000000
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Considerazione sull'efficienza: assegnamento
(le costanti si assegnano
solo durante l'inizializzazione)
è una costante intera
i
è una variabile intera
(vale 10)
ip è un puntatore ad un intero
del compilatore
int x;
...
I
tabella dei Simboli
const int I=10;
int i;
int* ip;
ide.
tipo
I
i
ip
x
int
int
int*
int
locazione o valore
--0xAA000000
10
---
0xBB000000
---
0xCC000000
---
I = 15;
i = 15;
compilazione
STORE
15
*ip = 15;
compilazione
READ
STORE
TEMP
15
Marco Tarini ‧ Laboratorio di Linguaggi ‧
0xAA000000
0xBB000000
TEMP
2004/05 ‧ Università dell’Insubria
Considerazione sull'efficienza: esercizio
accessi alla memoria
in scrittura
accessi alla memoria
in lettura
a = 15;
1
0
a = b;
1
1
a = *p;
1
2
*p = 15;
1
1
*p = b;
1
2
*p = *p2;
1
3
comando
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Algebra dei Puntatori
• L'operazione base sui puntatori:
somma con un intero
<puntatore ad un tipo T> + <intero>
espressione di tipo puntatore ad un tipo T (T*)
• Semantica:
p + i
• è il puntatore che punta una loc. i elementi (di tipo T ) dopo p;
• come indirizzo di memoria, è l'indirizzo p +
Marco Tarini ‧ Laboratorio di Linguaggi ‧
i x (dimensione diT )
2004/05 ‧ Università dell’Insubria
Algebra dei Puntatori
• Esempi
double *p, *q;
...
q = p + 3;
*(p + 3)=2.0;
q++;
q--;
q+=2;
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Algebra dei Puntatori
IDEONA !!
equivalenza
puntatori - vettori
Brain Kernighan
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Algebra dei Puntatori
• Ripasso: vettori
– in memoria, gli elementi di un array sono memorizzati
in una serie di celle contigue
– ogni cella ha la stessa grandezza
– per questo gli array sono random access!
int cartella[5]={
10,21,33,13,4,
};
indirizzo
base
di "cartella"
dimensione
cella (=4)
10
indirizzo di
21
33
13
4
cartella[3] = (indirizzo base) + 3 x (dimensione cella)
cartella[3]
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Algebra dei Puntatori
double *p;
...
p[ 5 ]
equivalente a
*(p + 5)
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Zucchero sintattico
typedef struct {
char nome[24];
char cognome[24];
int peso;
} Persona;
Persona *p;
...
come accedo al campo peso della Persona puntata da p?
*p.peso
interpretato
come
*
( p.peso )
(*p).peso
o, equivalentemente, con l'apposito operatore "freccina":
p->peso
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Zucchero sintattico
typedef struct {
char nome[24];
char cognome[24];
int peso;
} Persona;
typedef struct {
char nome[24];
char cognome[24];
int peso;
} Persona;
void pippo(Persona p) {
...
if (p.peso == ... )
...
}
void pippo(Persona* p) {
...
if (p->peso == ... )
...
}
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Assegnare i Puntatori
• In memoria, un puntatore è un indirizzo di memoria
– (...di una variabile)
– (...di cui e' noto il tipo)
• Bene, ma quale indirizzo?
– Modo 1: prendere l'indirizzo di una variabile esistente
• il puntatore punterà a quella variabile
– Modo 2: allocare (riservare, prenotare) della memoria libera
• il puntatore punterà ad una nuova variabile, memorizzata nella
memoria così riservata
• la nuova variabile è allocata dinamicamente!
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Assegnare i Puntatori
• Modo 1: prendere l'indirizzo di una variabile esistente
– il puntatore punterà a quella variabile
• Operatore "ampersand" (
• Esempio:
il puntatore p
punta
all'indirizzo di
memoria
dove vive la
variabile d
&
)
double d = 9.0;
double *p;
p = &d;
printf("%f",*p);
*p = 21.5;
printf("%f",d);
scrivi il valore
di *p .
Cosa scrive?
scrivi il valore
di d .
Cosa scrive?
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Operatore & e i tipi
• se y è una var di tipo T...
& y
T
T*
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Operatore
errore!
numeri non
è mica di tipo
int !
(e quindi
&numeri non
è di tipo
int* )
& e vettori
int numeri[]={10,20,30,40};
int *punt;
punt = & numeri;
scrivere invece:
punt = & (numeri[0]);
oppure anche (un'altra scorciatoia sintattica):
punt = numeri;
scriviamo tutti i 4 numeri:
int i;
for (i=0; i<4; i++) {
printf("%d ", numeri[i]);
}
Marco Tarini ‧ Laboratorio di Linguaggi ‧
usando i puntatori:
int i;
for (i=0; i<4; i++) {
printf("%d ", punt++);
}
2004/05 ‧ Università dell’Insubria
Altro Esempio
stringa
stringa[0]
'p'
p
stringa[1]
'u'
p
stringa[2]
'n'
p
stringa[3]
't'
p
stringa[4]
'a'
p
stringa[5]
't'
p
stringa[6]
'o'
p
stringa[7]
'r'
p
stringa[8]
'e'
p
stringa[9]
0
p
char stringa[]="puntatore";
int i;
while (stringa[i]) {
stringa[i] = maiuscolo(stringa[i]);
i++;
}
char stringa[]="Puntatore";
char *p = stringa;
while (*p) {
*p = maiuscolo( *p );
p++;
}
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Uso dei Puntatori come Parametri
• vi ricordate quel problemino?
void raddoppia (int
{
x = x * 2;
}
x)
int main(){
int incassi = 5;
raddoppia( incassi );
...
}
void raddoppia (int *x)
{
*x = *x * 2;
}
int main(){
int incassi = 5;
raddoppia( & incassi );
...
}
Remember: in C i paramatri sono passati per copia !
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria
Uso dei Puntatori come Parametri
• un'altra motivazione possibile: efficienza
typedef struct {
char nome[20];
char cognome[20];
int eta;
Esami* esami_sostenuti[50];
} Persona;
ogni volta che si chiama
questa funzione,
vengono copiati
sizeof(Persona)
bytes.
int eta_fra_10_anni (Persona pp)
{
return pp.eta + 10;
}
int eta_fra_10_anni (Persona * pp)
{
return pp->eta + 10;
}
Marco Tarini ‧ Laboratorio di Linguaggi ‧
ogni volta che si chiama
questa funzione,
vengono copiati
sizeof(Persona*)
bytes.
2004/05 ‧ Università dell’Insubria
Uso dei Puntatori come Parametri
• un'altra motivazione possibile: efficienza
int eta_fra_10_anni (Persona pp)
{
return pp.eta + 10;
}
inefficiente 
int eta_fra_10_anni (Persona * pp)
{
return pp->eta + 10;
}
efficiente 
In questi casi, però, meglio aggiungere anche la keyword
const
:
int eta_fra_10_anni (const Persona * pp)
{
return pp->eta + 10;
}
• più informazione presente nel codice per il programmatore
(come un commento)
• più ottimizzazioni possibili da parte del compilatore
• più controllo di errori a tempo di compilazione
(per esempio se per sbaglio si tenta di cambiare il valore del parametro)
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2004/05 ‧ Università dell’Insubria