Upload
rodolfo-bettini
View
228
Download
0
Embed Size (px)
Citation preview
PUNTATORI
• Un puntatore è una variabile destinata a contenere l’indirizzo di un’altra variabile
• Vincolo di tipo: un puntatore a T può contenere solo l’indirizzo di variabili di tipo T.
• Esempio:
int x = 8;int* p;p = &x; /* OK */
PUNTATORI
int x = 8;int* p;p = &x; /* OK */
Da questo momento, *p e x sono due modialternativi per denotare la stessa variabile
xp
8
PUNTATORI
int x = 8;int* p = &x;*p = 31; x--;
Il valore di *p, alias x, è ora 30.
Il valore di p, invece, rimane immutato.
xp
8 30
PUNTATORI
In questo momento, p punta a x, e perciò*p è un alias per x.
Ma un puntatore non è legato per semprealla stessa variabile: può puntare altrove.
int x = 8, y = 66;int *p = &x;(*p)++; /* incrementa x */p = &y; /* ora p punta a y */(*p)--; /* decrementa y */
PUNTATORI
In questo momento, p punta a x, e perciò*p è un alias per x.
Ma un puntatore non è legato per semprealla stessa variabile: può puntare altrove.
int x = 8, y = 66;int *p = &x;(*p)++; /* incrementa x */p = &y; /* ora p punta a y */(*p)--; /* decrementa y */
Le parentesi intorno a (*p)sono necessarie per modi-
ficare l’oggetto puntato da pe non p stesso.
PUNTATORI
• Un puntatore a T può contenere solo l’in-dirizzo di variabili di tipo T: puntatori a tipi diversi sono incompatibili tra loro.
• Esempio:
int x=8,*p; float *q;p = &x; /* OK */q = p; /* NO! */
MOTIVO: il tipo del puntatore serve per dedurre iltipo dell’oggetto puntato, che è una informazioneindispensabile per effettuare il dereferenziamento.
PUNTATORI
Forzare un assegnamento fra puntatori a tipidiversi è possibile mediante un cast esplici-to, ma è molto pericoloso!
int x=8,*p; float *q;q = (float*)&x;
ATTENZIONE!! • È facile scriverlo…• … ma quasi sempre si ottengono solo guai!
Aggirare il type system non è (quasi) mai una buona idea!!
IL SOLITO ESEMPIO
void scambia(int* pa, int* pb) { int t; t = *pa; *pa = *pb; *pb = t;}
main(){ int y = 5, x = 33; int *py = &y, *px = &x; scambia(px, py);} Variazione sul tema: gli indirizzi
di x e y sono posti in due puntatoripx e py prima di passarli.
PUNTATORI
• Un puntatore è una variabile destinata a contenere l’indirizzo di un’altra variabile
• Vincolo di tipo: un puntatore a T può contenere solo l’indirizzo di variabili di tipo T.
• Esempio:
int x = 8;int* p;p = &x; /* OK */
PUNTATORI
int x = 8;int* p;p = &x; /* OK */
Da questo momento, *p e x sono due modialternativi per denotare la stessa variabile
xp
8
PUNTATORI
int x = 8;int* p = &x;*p = 31; x--;
Il valore di *p, alias x, è ora 30.
Il valore di p, invece, rimane immutato.
xp
8 30
PUNTATORI
In questo momento, p punta a x, e perciò*p è un alias per x.
Ma un puntatore non è legato per semprealla stessa variabile: può puntare altrove.
int x = 8, y = 66;int *p = &x;(*p)++; /* incrementa x */p = &y; /* ora p punta a y */(*p)--; /* decrementa y */
PUNTATORI
In questo momento, p punta a x, e perciò*p è un alias per x.
Ma un puntatore non è legato per semprealla stessa variabile: può puntare altrove.
int x = 8, y = 66;int *p = &x;(*p)++; /* incrementa x */p = &y; /* ora p punta a y */(*p)--; /* decrementa y */
Le parentesi intorno a (*p)sono necessarie per modi-
ficare l’oggetto puntato da pe non p stesso.
PUNTATORI
• Un puntatore a T può contenere solo l’in-dirizzo di variabili di tipo T: puntatori a tipi diversi sono incompatibili tra loro.
• Esempio:
int x=8,*p; float *q;p = &x; /* OK */q = p; /* NO! */
MOTIVO: il tipo del puntatore serve per dedurre iltipo dell’oggetto puntato, che è una informazioneindispensabile per effettuare il dereferenziamento.
PUNTATORI
Forzare un assegnamento fra puntatori a tipidiversi è possibile mediante un cast esplici-to, ma è molto pericoloso!
int x=8,*p; float *q;q = (float*)&x;
ATTENZIONE!! • È facile scriverlo…• … ma quasi sempre si ottengono solo guai!
Aggirare il type system non è (quasi) mai una buona idea!!
IL SOLITO ESEMPIO
void scambia(int* pa, int* pb) { int t; t = *pa; *pa = *pb; *pb = t;}
main(){ int y = 5, x = 33; int *py = &y, *px = &x; scambia(px, py);} Variazione sul tema: gli indirizzi
di x e y sono posti in due puntatoripx e py prima di passarli.
IL SOLITO ESEMPIO
Osserva: pa e pb sono copie di px e py!
Il C passa davvero tuttosempre e solo per valore!
RADL
X
Y
PA
PB
33
5
5
33
T 33
RADL
px
py
ESERCIZIO
Scrivere una procedura che, dato un carattere C, lo trasformi in maiuscolo.
Specifica di I° livello:
void maiuscolo(char *pc);restituisce il maiuscolo di C
Specifica di II° livello:
Se *c non è una lettera minuscola, restituiscilo tale e quale. Altrimenti, per calcolare il corrispondente maiu-scolo, sfrutta l’ ordinamento della codifica dei caratteri:– ogni carattere è associato a un intero– le lettere da ‘A’ a ‘Z’ sono in sequenza– le lettere da ‘a’ a ‘z’ sono in sequenza
ESERCIZIO
void maiuscolo(char *pc) {if (*pc<'a' || *pc>'z') return;else *pc –= 'a' - 'A';
}
o anche:
void maiuscolo(char *pc) {if (*pc>='a' && *pc<='z')
*pc += 'A' - 'a';}
Cosa succede se si dimentica un asterisco?
COMUNICAZIONE TRAMITE ENVIRONMENT GLOBALE
Una procedura può anche comunicare conil suo cliente mediante aree dati globali: unesempio sono le variabili globali del C.
Esempio: Divisione intera x/y con calcolo di quoziente eresto.• occorre calcolare due valori• che supponiamo di mettere in due variabili
globali.
COMUNICAZIONE TRAMITE ENVIRONMENT GLOBALE
int quoziente, int resto;
void dividi(int x, int y) { resto = x % y; quoziente = x/y;}
main(){ dividi(33, 6);}
Il risultato è nelle variabili globali quoziente e resto:
il cliente deve andar-selo a prendere!Soprattutto, niente indica
che sia là: bisogna saperlo.
L’ENVIRONMENT GLOBALE
Le variabili globali in C:• sono allocate nell’area dati globale • esistono già prima della chiamata del main• sono inizializzate automaticamente a 0
salvo diversa indicazione (preferibile!!)• possono essere nascoste in una funzione
da una variabile locale omonima• sono visibili, previa dichiarazione extern,
in tutti i file dell’applicazione
L’ENVIRONMENT GLOBALE
Il fatto che le variabili globali in C siano visi-bili, previa dichiarazione extern, in tutti i filedell’applicazione pone dei problemi di prote-zione.
Potrebbe essere utile avere variabili globali• permanenti come tempo di vita• ma protette, nel senso che solo una parte
dell’applicazione possa accedervi.
VARIABILI STATICHE
In C, una variabile può essere dichiaratastatic. In questo modo, essa:• è permanente come tempo di vita• ed è protetta, in quanto è visibile solo
entro il suo scope di definizione.
Nel caso di una variabile globale, ognitentativo di accedervi da altri file, tramitedichiarazioni extern, sarà stroncato dalcompilatore.
ESEMPIO
static int cont = 3;
int nextValue(){return cont++;
}
• La variabile cont è inaccessibile fuori da questo file (il suo scope di definizione); l’unico modo di accedervi è tramite la funzione nextValue
• se un altro file definisse un’altra variabile globale cont, non ci sarebbe comunque collisione, perché la prima esternamente “non esiste”.
VARIABILI STATICHE
Una variabile statica può essere definitaanche dentro a una funzione. Così:• è comunque protetta, in quanto visibile solo
dentro alla funzione (come ogni variabile locale)
• ma è anche permanente, in quanto il suo tempo di vita diventa quello dell’intero programma.
È un mezzo per costruire componenti (fun-zioni) dotati di stato.
ESEMPIO
int nextPrime(void) { static lastprime = 0; if (lastprime>=0 && lastprime<=2)
return ++lastprime; else {
do lastprime += 2;while (!isPrime(lastprime));
return lastprime; }}
Questa funzione restituisce a ogni invocazione il suc-cessivo numero primo.
È un componente dotato di stato: chiamato più volte, dà ogni volta
una risposta diversa
VARIABILI STATICHE
Quindi, la parola chiave static• ha sempre e comunque due effetti
– rende la variabile permanente– rende la variabile protetta
(invisibile fuori dal suo scope di definizione)
• ma se ne vede sempre uno solo per volta– una variabile definita in una funzione, che è
comunque protetta, viene resa permanente– una variabile globale, già di per sé permanente,
viene resa protetta.
COMUNICAZIONE TRAMITE ENVIRONMENT GLOBALE
Una procedura può anche comunicare conil suo cliente mediante aree dati globali: unesempio sono le variabili globali del C.
Esempio: Divisione intera x/y con calcolo di quoziente eresto.• occorre calcolare due valori• che supponiamo di mettere in due variabili
globali.
COMUNICAZIONE TRAMITE ENVIRONMENT GLOBALE
int quoziente, int resto;
void dividi(int x, int y) { resto = x % y; quoziente = x/y;}
main(){ dividi(33, 6);}
Il risultato è nelle variabili globali quoziente e resto:
il cliente deve andar-selo a prendere!Soprattutto, niente indica
che sia là: bisogna saperlo.
L’ENVIRONMENT GLOBALE
Le variabili globali in C:• sono allocate nell’area dati globale • esistono già prima della chiamata del main• sono inizializzate automaticamente a 0
salvo diversa indicazione (preferibile!!)• possono essere nascoste in una funzione
da una variabile locale omonima• sono visibili, previa dichiarazione extern,
in tutti i file dell’applicazione
L’ENVIRONMENT GLOBALE
Il fatto che le variabili globali in C siano visi-bili, previa dichiarazione extern, in tutti i filedell’applicazione pone dei problemi di prote-zione.
Potrebbe essere utile avere variabili globali• permanenti come tempo di vita• ma protette, nel senso che solo una parte
dell’applicazione possa accedervi.
VARIABILI STATICHE
In C, una variabile può essere dichiaratastatic. In questo modo, essa:• è permanente come tempo di vita• ed è protetta, in quanto è visibile solo
entro il suo scope di definizione.
Nel caso di una variabile globale, ognitentativo di accedervi da altri file, tramitedichiarazioni extern, sarà stroncato dalcompilatore.
ESEMPIO
static int cont = 3;
int nextValue(){return cont++;
}
• La variabile cont è inaccessibile fuori da questo file (il suo scope di definizione); l’unico modo di accedervi è tramite la funzione nextValue
• se un altro file definisse un’altra variabile globale cont, non ci sarebbe comunque collisione, perché la prima esternamente “non esiste”.
VARIABILI STATICHE
Una variabile statica può essere definitaanche dentro a una funzione. Così:• è comunque protetta, in quanto visibile solo
dentro alla funzione (come ogni variabile locale)
• ma è anche permanente, in quanto il suo tempo di vita diventa quello dell’intero programma.
È un mezzo per costruire componenti (fun-zioni) dotati di stato.
ESEMPIO
int nextPrime(void) { static lastprime = 0; if (lastprime>=0 && lastprime<=2)
return ++lastprime; else {
do lastprime += 2;while (!isPrime(lastprime));
return lastprime; }}
Questa funzione restituisce a ogni invocazione il suc-cessivo numero primo.
È un componente dotato di stato: chiamato più volte, dà ogni volta
una risposta diversa
VARIABILI STATICHE
Quindi, la parola chiave static• ha sempre e comunque due effetti
– rende la variabile permanente– rende la variabile protetta
(invisibile fuori dal suo scope di definizione)
• ma se ne vede sempre uno solo per volta– una variabile definita in una funzione, che è
comunque protetta, viene resa permanente– una variabile globale, già di per sé permanente,
viene resa protetta.
FUNZIONI STATICHE
Nel secondo significato (protezione enascondimento), la parola chiave static può qualificare anche una funzione.
– rende la funzione protetta(invisibile fuori dal file di definizione)
– può servire per funzioni “a uso interno”, non destinate a essere invocate da altri
static int f(...) {...}