Upload
flavia-isernia
View
44
Download
0
Embed Size (px)
Citation preview
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 1/14
I puntatori
Ver. 2.4
© 2010 - Claudio Fornaro - Corso di programmazione in C
2
Puntatore E’ una variabile che contiene l’indirizzo di
memoria di un oggetto (variabile o costante) Esempiop è un puntatore e “punta” alla variabile x che inquesto esempio ha indirizzodi memoria A55)
int x=12;
12x:A55
p
A55 A55
...
...
...
...
12
A50
A51
A52
A53
A54
A55
p
x
3
Definizione Sintassi
tipo *nomeVariabile;
Esempiint *punt;
char x, *p, *q, y;
x e y sono variabili di tipo char
p e q sono variabili di tipo puntatore-a- char
4
Assegnazione Ad un puntatore si possono assegnare solo
indirizzi di memoria o il valore NULL che indicache il puntatore non punta a nulla
La costante 0 in un contesto dove è atteso unpuntatore (inizializzazione e assegnamento diun puntatore, confronto con un puntatore)viene convertita in NULL dal compilatore
L’ operatore di indir izzo ‘&’ (“ampersand”)calcola l’indirizzo di memoria di una variabile
(si dice che ne restituisce il puntatore)int *p = &x; inizializza p con l’indirizzo di xp = &y; assegna a p l’indirizzo di y
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 2/14
5
Utilizzo Si accede all’oggetto puntato da un puntatore
per mezzo dell’operatore ‘* ’ dettooperatore di deriferim ento (“dereference”)o di indirezione (“indirection”)
int x=12, *p = &x; p “punta a” x*p = 24; x ora vale 24 *p += 6; x ora vale 30
p è il puntatore*p è l’oggetto puntato (qui è x)
Si noti che la sintassi per indicare l’oggettopuntato e quella della definizione del puntatoresono identiche: *p
6
Utilizzo Sia p sia *p sono L-value modificabili , ossia
sono un “qualcosa” (variabile, elemento divettore, …) a cui si può assegnare un valore
L’operatore ‘*’ ha priorità superiore a quelladegli operatori matematicix = 6 * *p; equivale a: x = 6 * (*p);
Per visualizzare il valore di un puntatore sipuò utilizzare la direttiva %p in una printf
7
Tipi e puntatori L’informazione relativa al tipo è necessaria per
permettere ai puntatori di conoscere ladimensione dell’oggetto puntato (usata
nell’aritmetica dei puntatori) Poiché oggetti di tipo diverso possono avere
dimensione diversa, l’assegnazione trapuntatori di tipo diverso è in genere errata e ilcompilatore genera un warningint *p, x=12;long *q, y=26;
p = &x; OK! q = &y; OK! q = p; NO! Warning q = &x; NO! Warning
8
Puntatori a void Sono puntatori generici e non possono essere
dereferenziati (non si può scrivere *p),
possono essere utilizzati solo come contenitori temporanei di valori di tipo puntatore (aqualsiasi tipo)void *h;
Non serve il cast (void *) per copiare unpuntatore non-void in un puntatore void
h = p; (supponendo ad esempio int *p )
Qualsiasi tipo di puntatore può essereconfrontato con un puntatore a void
NULL è definito come: (void *)0
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 3/14
9
Puntatori a void Per dereferenziare il valore di un puntatore avoid è necessario assegnarlo ad un puntatoreal tipo appropriato (non void) per poterconoscere la dimensione dell’oggetto puntato
Può essere necessario il cast (tipo *) percopiare un puntatore void in un puntatorenon-void (i compilatori C non lo richiedono, icompilatori C++ sì).
In riferimento all’esempio precedente:int *q;
q = h; OK, compilatore C q = (int *)h; OK, compilatore C++ *q = 23; x ora contiene 23
10
Puntatori e vettori Il nome (senza parentesi) di un vettore-di-T
è un valore costante di tipo puntatore-a-T ,corrisponde all’indirizzo di memoria del primoelemento di vettore
int vett[100];
int *p;
p = vett;
l’indirizzo di memoria di vett viene messo inp, equivale a scrivere: p = &vett[0] (leparentesi hanno priorità maggiore di &)
11
Puntatori e vettori Attenzione:vett = p; NO! Non si può assegnare un valore a vett inquanto NON è una variabile puntatore, ma un “sinonimo” di un indirizzo di memoria
Gli indirizzi di memoria sono valori costanti stabiliti dal compilatore, non sono variabili equindi non hanno uno spazio in memoriamodificabile per contenere un valore
Il termine “puntatore” viene comunemente (eimpropriamente) usato al posto di “indirizzo dimemoria” (es. “&a dà il puntatore ad a”)
12
Equivalenza puntatori e vettori Una variabile di tipo puntatore-a-T , assegnata
in modo che punti a (cioè contenga l’indirizzodi) un oggetto di tipo vettore-di-T , può essere
utilizzata come se fosse un vettore-di-T int vett[25];
int *p = vett;
Ad esempio, qui p[3] equivale a vett[3]
Il compilatore internamente trasforma leespressioni con notazione vettoriale [] inespressioni con i puntatori
vett:
p
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 4/14
13
Aritmetica dei puntatori Quando un puntatore punta ad un vettore,
gli può essere sommato un valore intero N, ilrisultato è l’indirizzo di memoria dell’elementodi posizione N del vettore
p punta a (contiene l'indirizzo di) vettp+3 punta a (produce l'indir. di) vett[3]*(p+3) equivale a vett[3]
2732 15 23 55 32 11
vett:
p+3p
14
Aritmetica dei puntatori L’istruzione p++ porta p a puntare a vett[1]
(ne contiene l’indirizzo) quindi ora p punta avett[1] e p[3] corrisponde a vett[4]
E’ lecito sottrarre un valore N ad un puntatorese l’elemento puntato risultante fa ancora partedel vettore (nell’esempio precedente p-1
punta a vett[0])
2732 15 23 55 32 11
vett:
p+3p
15
Equivalenza puntatori e vettori Il nome di un vettore può essere utilizzato
come puntatore costante :*(vett+2) equivale a: vett[2]vett++ è un errore ( vett è costante!)
Il nome di un vettore di T (es. int) chedovrebbe essere una costante di tipo puntatore-a-vettore -di-T (o meglioindirizzo-di-vettore-di-T ), in C “decade” altipo puntatore -a-T
Grazie al decadimento vett è visto comepuntatore (costante) a int e punta al suoprimo elemento e vett+1 punta a vett[1]
16
Equivalenza puntatori e vettori Senza il decadimento, vett+1 punterebbe al
primo byte dopo la fine di vett
Eccezioni: vett in un sizeof (descritto altrove) non decade
e per questo dà la dimensione dell’intero vettore,non quella del primo elemento
&vett inibisce il decadimento e produce unaquantità costante di tipo puntatore-a-vettore-di- int
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 5/14
17
Equivalenza puntatori e vettori Una variabile di tipo puntatore-a-T non “sa”
se il valore (scalare) a cui punta è singolo o èl’elemento di un vettore, lo sa solo ilprogrammatore e sta a questi utilizzarlo inmodo coerente
int x = 10, vett[10], *p, *q;
p = &x;
p++; NO! Non esiste l’oggetto puntato da p+1q = p+1; NO! Idem
p = vett;
p++; SI’! Ora p punta a vett[1]q = p+1; SI’! Ora q punta a vett[2]
18
Aritmetica dei puntatori Attenzione che il puntatore non “sfori” i limiti
del vettore (lo standard non richiede che ilcompilatore faccia controlli, molti compilatorilo offrono opzionalmente, ma ciò riduce leprestazioni)
E’ lecito che un puntatore punti a quello chesarebbe l’elemento del vettore successivo all’ultimo , ma questo puntatore può essere
utilizzato solo per calcolare la differenza trapuntatori (vedere prossima slide)
19
Aritmetica dei puntatori Due puntatori a elementi dello stesso vettore
possono essere sottrat t i , il valore ottenuto +1 è il numero di elementi del vettore compresitra quelli puntati dai due puntatori (inclusi):p = &vett[4];
q = &vett[10];
d = q-p+1; 7: numero degli elementidalla posizione 4 allaposizione 10 inclusi
Due puntatori possono essere confrontati solo se fanno parte dello stesso vettore oppureuno dei due è NULL (o 0)
20
Priorità dell’operatore * Dalla tabella delle priorità si vede che
l’operatore di deriferimento * ha priorità quasimassima, inferiore solo alle parentesi (e a ‘->’ e a ‘.’) e associatività da destra a sinistra
Quindi, considerando che gli operatori * e ++
hanno stessa priorità e associatività da D a S:*p++ equivale a *(p++) incrementa p
*++p equivale a *(++p) incrementa p
++*p equivale a ++(*p) incrementa *p
inoltre:(*p)++ incrementa *p
*p+1 equivale a (*p)+1 e non a *(p+1)
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 6/14
21Copia di stringhe1a versione
La stringa y viene copiata in xchar x[30], y[30], *t=x, *s=y;
int i=0;gets(y);while (s[i] != '\0'){
t[i] = s[i];i++;
}
t[i] = '\0';printf("%s\n", x);
Il '\0' viene copiato fuori dal ciclo Qui s e t vengono inutilmente usati come
semplici sinonimi di x e y, non come puntatori
22Copia di stringhe2a versione
La stringa y viene copiata in x
char x[30], y[30], *t=x, *s=y;
int i=0;
gets(y);
while ((t[i] = s[i]) != '\0')
i++;
printf("%s\n", x);
Il '\0' viene copiato nel ciclo stesso
Qui s e t vengono inutilmente usati comesemplici sinonimi di x e y, non come puntatori
Nota: non si può scrivere t[i] = s[i++]nella condizione del while (side effect)
23Copia di stringhe3a versione
La stringa y viene copiata in x
char x[30], y[30], *t=x, *s=y;
gets(y);
while ( (*t = *s) != '\0')
{
t++;
s++;
}
printf("%s\n", x);
Il '\0' viene copiato nel ciclo stesso Nota: != '\0' può essere omesso
24Copia di stringhe4a versione
La stringa y viene copiata in x
char x[30], y[30], *t=x, *s=y;
gets(y);
while (*t++ = *s++)
;
printf("%s\n", x);
Il '\0' viene copiato nel ciclo stesso
Nota: l‘istruzione nulla è più chiara se scritta
in una riga a sé stante
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 7/14
25
Puntatori e stringhe Si noti la differenza tra le seguenti definizioni:
char str[100];
RISERVA spazio per contenere i caratteri, è unavariabile e il suo contenuto può essere modificato
char *s;
NON RISERVA spazio per contenere i caratteri,quindi per essere utilizzata come stringa le si deveassegnare una stringa “vera”:
Assegnazione di una stringa variabile: s = str;
scanf("%s", s); SI’
Assegnazione di una stringa costante: s = "salve";
scanf("%s", s); NO
26
Puntatori e stringhe Si considerino i seguenti esempi:
char str[] = "ciao";
E’ l’ inizializzazione di una variabile stringa:il compilatore riserva memoria per str e vi copia icaratteri di "ciao"; la stringa costante "ciao"non esiste in memoria: è stata usata dalcompilatore per inizializzare la stringa str, maesiste in memoria la stringa variabile "ciao"str[0]='m'; SI’
char *s = "hello";E’ l’ inizializzazione di una variabile puntat ore:il compilatore determina l’indirizzo della stringa costante "hello" (che esiste in memoria) e loassegna alla variabile puntatore s
s[0]='b'; NO! "hello" è costante!
27
Puntatori e stringhe Si considerino i seguenti esempi (cont.):
s = "salve";
E’ l’ assegnazione ad una variabile puntator e: il
compilatore determina l’indirizzo della stringa costante "salve" (che esiste in memoria) e loassegna alla variabile puntatore s
s[4]='o'; NO! "salve" è costante!
s = str;
E’ l’ assegnazione ad una variabile puntator e: ilcompilatore determina l’indirizzo della stringa
variabile str (che esiste in memoria) e lo assegnaalla variabile puntatore s
s[0]='m'; SI’
28
Puntatori e stringhe Noti i puntatori, si possono completare le
informazioni già date sulle funzioni relativealle stringhe aggiungendo quanto segue: le funzioni di copia di stringhe strcpy, strncpy,strcat e strncat restituiscono il puntatore allastringa di destinazione
le funzioni di parsing strchr, strrchr, strstr,strpbrk e strtok restituiscono il puntatoreall’oggetto cercato o NULL se non lo trovano
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 8/14
29
Funzioni sui blocchi di byte Blocchi di byte: sequenze di byte (caratteri)
qualsiasi, il carattere di codice ASCII 0 ('\0')
è un carattere normale e non viene utilizzatocome terminatore (non c’è alcun terminatore)
Una porzione di memoria (allocata in qualsiasimodo) viene trattata come generico blocco dibyte da alcune funzioni contenute in<string.h>
Per riservare una porzione di memoria si puòdefinire una variabile o una stringa o utilizzarela funzione malloc (trattata in altre slide)
Nelle seguenti funzioni, s (source ) et (target ) sono puntatori a blocchi di byte
30
Funzioni sui blocchi di byte memcpy(t ,s,n)
copia n byte da s a t memmove(t ,s,n)
copia n byte da s a t (i blocchi possono anche essere sovrapposti)
memcmp(s,t ,n)
confronta byte per byte secondo il codice ASCII i primi n byte di s e di t , il valorerestituito è un int come quello della strcmp
memchr(s,c,n)cerca il byte c tra i primi n byte di s, dà NULL
se non lo trova o il puntatore ad esso se trova memset(s,c,n)
copia il byte c in tutti i primi n byte di s
31Puntatori constPuntatore variabile a valore costante
int const *p;
const int *p;
p è una variabile di tipo puntatore-a-costante (a un oggetto costante di tipo int)const int x, y;
const int *p; puntatore-a-costante p = &x; SI’, p è una variabile p = &y; SI’, p è una variabile *p = 13; NO, *p è costante
sono equivalenti }
32Puntatori constPuntatore variabile a valore costante
L’assegnazione di un valore di tipo puntatore- a-costante (l’indirizzo di un valore costante) aduna variabile di tipo puntatore-a-variabile genera un Warning del compilatore perchépermette di by-passare la restrizione (const)
const int x = 12;
int y = 10;
int *p; puntatore-a-variabile const int *q; puntatore-a-costante
p = &x;
Warning *p = 5; non dà errore q = &x; OK *p = 5; dà errore
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 9/14
33Puntatori constPuntatore costante a valore variabile
int * const p;
p è una costante di tipo puntatore-a-variabile (a un oggetto variabile di tipo int)
Le costanti possono essere solo inizializzate
int x, y;
int * const p = &x; inizializzazione *p = 13; SI’, *p è una variabile p = &y; NO, p è una costante
34
Esercizi1. Si scriva un programma che chieda una
stringa all’utente e conti quanti siano icaratteri che la costituiscono, NON si usi lafunzione strlen della libreria standard.
2. Scrivere un programma che verifichi se lastringa data in input è palindroma o no
3. Scrivere un programma che chieda n valoriinteri (massimo 100), li collochi in un vettore einverta il vettore (scambiando il primoelemento con l'ultimo, il secondo con ilpenultimo, etc.). Si usi la notazione vettoriale.
4. Come il precedente, ma si usino i puntatori.
35
Esercizi5. Scrivere un programma che data una stringa
in input dica se la stessa contiene almeno una ‘A’ tra i primi 10 caratteri.
6. Si scriva un programma che chieda all’utente2 stringhe e concateni la seconda alla finedella prima, NON si usi la funzione strcatdella libreria standard, si usino i puntatori enon la notazione vettoriale. Attenzione aterminarla con il carattere ‘\0’.
7. Si scriva un programma che chieda all’utente2 stringhe e indichi se la seconda è ugualealla parte terminale della prima.
36
Esercizi8. Scrivere un programma che chieda N valori
(massimo 100), li collochi in un vettore e liordini in senso crescente (senza usare vettoriausiliari).
9. Scrivere un programma che verifichi se lastringa data è composta di due parti uguali,trascurando il carattere centrale se lalunghezza è dispari (es. “CiaoCiao”, “CiaoXCiao”).
10. Scrivere un programma che date 2 stringhe ininput indichi quante volte la più corta ècontenuta nella più lunga.
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 10/14
37
Esercizi11. Scrivere un programma che legga da un file
un testo e spezzi su più righe quelle piùlunghe di N caratteri (N chiesto all’utente). Lerighe si possono spezzare solo dove c’è unospazio (che non va riportato nella rigasuccessiva). L’output deve essere salvato inun altro file.
38
Vettori di puntatori Gli elementi di questi vettori sono puntatoriint *vett[10];
definisce un vettore di 10 puntatori a int (le[ ] hanno priorità maggiore dell’operatore *)
Esempio di inizializzazioneint a, b, c;int *vett[10]={NULL};vett[0]=&a;vett[1]=&b;
vett[2]=&c;I valori da vett[3] a vett[9] sono tuttiNULL in quanto è stato inizializzato il primoelemento (i successivi sono automaticamentea 0 e 0 viene convertito in NULL)
39
Vettori di puntatori Esempio di inizializzazione errataint a, b, c;
int *vett[10]={&a, &b, &c};
E’ errato perché questi inizializzatori sonoindirizzi di variabili automatiche (descritto inaltre slide). Se le variabili fossero invece diclasse static sarebbe stato corretto, perqueste variabili i valori di vett si devonoassegnare come visto nell’esempio precedente
40
Puntatori a puntatori Variabili che contengono l'indirizzo di memoria
di un puntatore Esempioint a, *b, **c;a = 12;b = &a;c = &b;
Il puntatore c punta ad una variabile (b) chepunta ad un int (a)
12
c:5D6
A5B
B4Ab:A5B
a:B4A
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 11/14
41
Puntatori a puntatori Esempioint a=10, b=20, c=30;
int *v[3], int **w;v[0]=&a; v[1]=&b; v[2]=&c;
w = v;
w++;
v è un vettore di puntatori, cioè è l'indirizzo dimemoria (“puntatore”) di un puntatore, quindiv+1 è l'indirizzo del secondo puntatore del
vettore v (ossia è pari a &v[1], punta a b) Anche w è un puntatore ad un puntatore,quando viene incrementato, punta alpuntatore successivo, come v
42
Puntatori e matrici Una matrice è un vettore di vettori e quindi,
considerando che l’associatività di [] è da
sinistra a destra, si ha che:int Mx[7][5];
definisce un vettore di 7 elementiciascuno delle quali è un vettore di 5 int
Gli elementi del vettore Mx sono i 7 vettoriidentificati da Mx[i]; quindi Mx[i] è l’ indirizzo di memoria di ciascuno dei 7 vettori di 5 int
Poiché in seguito al decadimento il nome di unvettore-di-T ha tipo puntatore-a-T , anche gliMx[i] non sono di tipo vettore-di- int madecadono al tipo puntatore-a- int, (essendoindirizzi, non si può assegnare loro un valore)
43
Puntatori e matrici Il “decadimento” del tipo del nome di un
vettore a puntatore può avvenire 1 sola volta
Allora il tipo di una matrice decade a puntatore-a-vettore-di-T e non a puntatore-a- T (quindi incrementando questo puntatore sipunta al vettore di 5 int successivo)
Mx non è di tipo puntatore-a- int come:int *p
Mx non è di tipo puntatore-a-puntatore-a- int:int **p
Mx è di tipo puntatore-a-vettore-di-5- intcome: int (*p)[5]
quindi Mx+1 punta al secondo vettore di 5 int
44
Puntatori e matrici Nella definizione di puntatore seguenteint (*p)[5]
è necessario che la dimensione delle colonne(5) sia specificata perché definisce un puntatore-a-vettore-di- cinque -interi
Poiché Mx è un puntatore-a-vettore-di- 5 -interi (e non un puntatore ad un intero), allora:Mx+1 punta all’elemento successivo, ossia alsuccessivo vettore di 5 interi (la seconda riga
della matrice): Mx+1 aggiunge all’indirizzo diMx il numero corretto di byte per puntare alsecondo vettore di 5 int
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 13/14
49
Vettori di puntatori e matrici Si notino le differenze tra:char a[4][8]={"un","otto","sei"};
char *b[4]={"un","otto","sei"};
a[i]è l’indirizzo costante della riga i di a, taleriga è una stringa variabile di 8 char
b[i] è una variabile puntatore con l’indirizzodella riga i, stringa costante di 4 caratteri: adesempio b[2] contiene l’indirizzo di "sei\0"
un\0
otto\0
sei\0NULL
a: b:un\000000
otto\0000
sei\00000
\00000000
50
Vettori di puntatori e matrici a[2] = "hello";
ERRORE: a[2]non è un puntatore
strcpy(a[2], "hello");CORRETTO
b[2] = "hello";
CORRETTO: b[2] è una variabile puntatore a cuiviene assegnato l’indirizzo di memoria di una stringacostante strcpy(b[2], "hello");
ERRORE: b[2] punta a una stringa costante Entrambi a[1][0] e b[1][0] sono il carattere 'c'
a[1][0]='m'; SI’! L’oggetto puntato da a[1] è una stringa variabile
b[1][0]='m'; NO! L’oggetto puntato da b[1] è una stringa costante
51
Const per puntatori a puntatori1. int** x;
x è una variabile di tipo puntatorea un puntatore variabile
a un oggetto variabile di tipo int2. const int** x;
x è una variabile di tipo puntatorea un puntatore variabilea un oggetto costante di tipo int
3. int ** const x;
x è una costante di tipo puntatore
a un puntatore variabilea un oggetto variabile di tipo int
52
Const per puntatori a puntatori4. int * const * x
x è una variabile di tipo puntatorea un puntatore costante
a un oggetto variabile di tipo int5. const int * const * x
x è una variabile di tipo puntatorea un puntatore costantea un oggetto costante di tipo int
6. const int * const * const x
x è una costante di tipo puntatore
a un puntatore costantea un oggetto costante di tipo int
5/14/2018 Puntatori - PoliTo - slidepdf.com
http://slidepdf.com/reader/full/puntatori-polito 14/14
53
Homework 7Scrivere un programma che legga da un file almassimo un certo numero MAXRIGHE di righe di
testo e le memorizzi in una matrice di caratteri(MAXRIGHE x 100), una riga del file perciascuna riga della matrice.Si definisca un vettore di puntatori a carattere elo si inizializzi in modo che il primo puntatorepunti alla prima riga, il secondo alla seconda,ecc. Si ordinino le stringhe scambiando tra di
loro solo i puntatori e le si visualizzino ordinate.Facoltativo: misurare il rapporto tra il temponecessario per ordinare scambiando le stringhee scambiando i puntatori.
54
Homework 7 (esempio)
ché la diritta via era smarrita.
Nel mezzo del cammin di nostra vita
esta selva selvaggia e aspra e forte
mi ritrovai per una selva oscura
Ahi quanto a dir qual era è cosa dura
ché la diritta via era smarrita.
Nel mezzo del cammin di nostra vita
esta selva selvaggia e aspra e forte
mi ritrovai per una selva oscura
Ahi quanto a dir qual era è cosa dura
prima
dopo