380 likes | 504 Views
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 */. p. . x. . . 8. PUNTATORI. int x = 8;
E N D
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 */
p x 8 PUNTATORI int x = 8; int* p; p = &x; /* OK */ Da questo momento, *p e x sono due modi alternativi per denotare la stessa variabile
p x 8 30 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.
PUNTATORI In questo momento, p punta a x, e perciò *p è un alias per x. Ma un puntatorenon è legato per sempre alla 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 puntatorenon è legato per sempre alla 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 il tipo dell’oggetto puntato, che è una informazione indispensabile per effettuare il dereferenziamento.
PUNTATORI Forzare un assegnamento fra puntatori a tipi diversi è 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 */
p x 8 PUNTATORI int x = 8; int* p; p = &x; /* OK */ Da questo momento, *p e x sono due modi alternativi per denotare la stessa variabile
p x 8 30 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.
PUNTATORI In questo momento, p punta a x, e perciò *p è un alias per x. Ma un puntatorenon è legato per sempre alla 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 puntatorenon è legato per sempre alla 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 il tipo dell’oggetto puntato, che è una informazione indispensabile per effettuare il dereferenziamento.
PUNTATORI Forzare un assegnamento fra puntatori a tipi diversi è 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!
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 con il suo cliente mediante aree dati globali: un esempio sono le variabili globali del C. Esempio: Divisione intera x/y con calcolo di quoziente e resto. • 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 globaliin 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 globaliin C siano visi- bili, previa dichiarazione extern, in tutti i file dell’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 dichiarata static. 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, ogni tentativo di accedervi da altri file, tramite dichiarazioni extern, sarà stroncato dal compilatore.
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 staticapuò essere definita anche 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- cessivonumero primo. È un componente dotato di stato: chiamato più volte, dà ogni voltauna 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 con il suo cliente mediante aree dati globali: un esempio sono le variabili globali del C. Esempio: Divisione intera x/y con calcolo di quoziente e resto. • 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 globaliin 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 globaliin C siano visi- bili, previa dichiarazione extern, in tutti i file dell’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 variabilepuò essere dichiarata static. 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, ogni tentativo di accedervi da altri file, tramite dichiarazioni extern, sarà stroncato dal compilatore.
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 staticapuò essere definita anche 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- cessivonumero primo. È un componente dotato di stato: chiamato più volte, dà ogni voltauna 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 e nascondimento), 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(...) { ... }