Puntatore I puntatori - Politecnico di Torino: Aree Web personali / staff. ?· 2010-02-24 · puntatore…

  • Published on
    17-Feb-2019

  • View
    212

  • Download
    0

Embed Size (px)

Transcript

I puntatori

Ver. 2.4

2010 - Claudio Fornaro - Corso di programmazione in C

2

Puntatore E una variabile che contiene lindirizzo di

memoria di un oggetto (variabile o costante) Esempiop un puntatore e puntaalla variabile x che in questo esempio ha indirizzodi memoria A55)int x=12;

12

x:A55

pA55 A55

...

...

...

...

12

A50A51A52A53A54A55

p

x

3

Definizione Sintassi

tipo *nomeVariabile; Esempiint *punt;char x, *p, *q, y;x e y sono variabili di tipo charp 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 indica che il puntatore non punta a nulla

La costante 0 in un contesto dove atteso un puntatore (inizializzazione e assegnamento di un puntatore, confronto con un puntatore) viene convertita in NULL dal compilatore

Loperatore di indirizzo & (ampersand) calcola lindirizzo di memoria di una variabile (si dice che ne restituisce il puntatore)int *p = &x; inizializza p con lindirizzo di xp = &y; assegna a p lindirizzo di y

5

Utilizzo Si accede alloggetto puntato da un puntatore

per mezzo delloperatore * dettooperatore di deriferimento (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 loggetto puntato (qui x)

Si noti che la sintassi per indicare loggetto puntato e quella della definizione del puntatore sono identiche: *p

6

Utilizzo Sia p sia *p sono L-value modificabili, ossia

sono un qualcosa (variabile, elemento di vettore, ) a cui si pu assegnare un valore

Loperatore * ha priorit superiore a quella degli operatori matematicix = 6 * *p; equivale a: x = 6 * (*p);

Per visualizzare il valore di un puntatore si pu utilizzare la direttiva %p in una printf

7

Tipi e puntatori Linformazione relativa al tipo necessaria per

permettere ai puntatori di conoscere la dimensione delloggetto puntato (usata nellaritmetica dei puntatori)

Poich oggetti di tipo diverso possono avere dimensione diversa, lassegnazione tra puntatori di tipo diverso in genere errata e il compilatore genera un warning int *p, x=12;long *q, y=26;p = &x; OK!q = &y; OK!q = p; NO! Warningq = &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 contenitoritemporanei di valori di tipo puntatore (a qualsiasi tipo)void *h;

Non serve il cast (void *) per copiare un puntatore non-void in un puntatore voidh = p; (supponendo ad esempio int *p)

Qualsiasi tipo di puntatore pu essere confrontato con un puntatore a void

NULL definito come: (void *)0

9

Puntatori a void Per dereferenziare il valore di un puntatore a void necessario assegnarlo ad un puntatore al tipo appropriato (non void) per poter conoscere la dimensione delloggetto puntato

Pu essere necessario il cast (tipo *) per copiare un puntatore void in un puntatore non-void (i compilatori C non lo richiedono, i compilatori C++ s).In riferimento allesempio precedente:int *q;q = h; OK, compilatore Cq = (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 allindirizzo di memoria del primo elemento di vettoreint vett[100];int *p;p = vett; lindirizzo di memoria di vett viene messo in p, equivale a scrivere: p = &vett[0] (le parentesi hanno priorit maggiore di &)

11

Puntatori e vettori Attenzione:vett = p; NO!Non si pu assegnare un valore a vett in quanto NON una variabile puntatore, ma un sinonimo di un indirizzo di memoriaGli indirizzi di memoria sono valori costantistabiliti dal compilatore, non sono variabili e quindi non hanno uno spazio in memoria modificabile per contenere un valoreIl termine puntatore viene comunemente (e impropriamente) usato al posto di indirizzo di memoria (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 lindirizzo di) un oggetto di tipo vettore-di-T , pu essere utilizzata come se fosse un vettore-di-Tint vett[25];int *p = vett;

Ad esempio, qui p[3] equivale a vett[3] Il compilatore internamente trasforma le

espressioni con notazione vettoriale [] in espressioni con i puntatori

vett:p

13

Aritmetica dei puntatori Quando un puntatore punta ad un vettore,

gli pu essere sommato un valore intero N, il risultato lindirizzo di memoria dellelemento di 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 11vett:

p+3p

14

Aritmetica dei puntatori Listruzione p++ porta p a puntare a vett[1]

(ne contiene lindirizzo) quindi ora p punta a vett[1] e p[3] corrisponde a vett[4]

E lecito sottrarre un valore N ad un puntatore se lelemento puntato risultante fa ancora parte del vettore (nellesempio precedente p-1punta 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) che dovrebbe essere una costante di tipo puntatore-a-vettore-di-T (o meglio indirizzo-di-vettore-di-T ), in C decade al tipo puntatore-a-T

Grazie al decadimento vett visto come puntatore (costante) a int e punta al suo primo 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 dellintero vettore, non quella del primo elemento

&vett inibisce il decadimento e produce una quantit costante di tipo puntatore-a-vettore-di-int

17

Equivalenza puntatori e vettori Una variabile di tipo puntatore-a-T non sa

se il valore (scalare) a cui punta singolo o lelemento di un vettore, lo sa solo il programmatore e sta a questi utilizzarlo in modo coerenteint x = 10, vett[10], *p, *q;p = &x;p++; NO! Non esiste loggetto puntato da p+1q = p+1; NO! Idemp = 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 il compilatore faccia controlli, molti compilatori lo offrono opzionalmente, ma ci riduce le prestazioni)

E lecito che un puntatore punti a quello che sarebbe lelemento del vettore successivo allultimo, ma questo puntatore pu essere utilizzato solo per calcolare la differenza tra puntatori (vedere prossima slide)

19

Aritmetica dei puntatori Due puntatori a elementi dello stesso vettore

possono essere sottratti, il valore ottenuto + 1 il numero di elementi del vettore compresi tra quelli puntati dai due puntatori (inclusi):p = &vett[4];q = &vett[10];d = q-p+1; 7: numero degli elementi

dalla posizione 4 allaposizione 10 inclusi

Due puntatori possono essere confrontatisolo se fanno parte dello stesso vettore oppure uno dei due NULL (o 0)

20

Priorit delloperatore * Dalla tabella delle priorit si vede che

loperatore di deriferimento * ha priorit quasi massima, 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 *pinoltre:(*p)++ incrementa *p*p+1 equivale a (*p)+1 e non a *(p+1)

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 stringhe 2a versione La stringa y viene copiata in xchar 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 come

semplici 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 xchar 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 xchar 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: listruzione nulla pi chiara se scritta

in una riga a s stante

25

Puntatori e stringhe Si noti la differenza tra le seguenti definizioni:

char str[100];RISERVA spazio per contenere i caratteri, una variabile e il suo contenuto pu essere modificato

char *s;NON RISERVA spazio per contenere i caratteri, quindi per essere utilizzata come stringa le si deve assegnare 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 linizializzazione di una variabile stringa:il compilatore riserva memoria per str e vi copia i caratteri di "ciao"; la stringa costante "ciao"non esiste in memoria: stata usata dal compilatore per inizializzare la stringa str, ma esiste in memoria la stringa variabile "ciao"str[0]='m'; SI

char *s = "hello";E linizializzazione di una variabile puntatore: il compilatore determina lindirizzo della stringa costante "hello" (che esiste in memoria) e lo assegna alla variabile puntatore ss[0]='b'; NO! "hello" costante!

27

Puntatori e stringhe Si considerino i seguenti esempi (cont.):

s = "salve";E lassegnazione ad una variabile puntatore: il compilatore determina lindirizzo della stringa costante "salve" (che esiste in memoria) e lo assegna alla variabile puntatore ss[4]='o'; NO! "salve" costante!

s = str;E lassegnazione ad una variabile puntatore: il compilatore determina lindirizzo della stringa variabile str (che esiste in memoria) e lo assegna alla variabile puntatore ss[0]='m'; SI

28

Puntatori e stringhe Noti i puntatori, si possono completare le

informazioni gi date sulle funzioni relative alle stringhe aggiungendo quanto segue: le funzioni di copia di stringhe strcpy, strncpy, strcat e strncat restituiscono il puntatore alla stringa di destinazione

le funzioni di parsing strchr, strrchr, strstr, strpbrk e strtok restituiscono il puntatore alloggetto cercato o NULL se non lo trovano

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 utilizzato come terminatore (non c alcun terminatore)

Una porzione di memoria (allocata in qualsiasi modo) viene trattata come generico blocco di byte da alcune funzioni contenute in

Per riservare una porzione di memoria si pu definire una variabile o una stringa o utilizzare la funzione malloc (trattata in altre slide)

Nelle seguenti funzioni, s (source) e t (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 valore restituito un int come quello della strcmp

memchr(s,c,n)cerca il byte c tra i primi n byte di s, d NULLse 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-costantep = &x; SI, p una variabilep = &y; SI, p una variabile*p = 13; NO, *p costante

sono equivalenti}

32Puntatori constPuntatore variabile a valore costante Lassegnazione di un valore di tipo puntatore-

a-costante (lindirizzo di un valore costante) ad una variabile di tipo puntatore-a-variabilegenera un Warning del compilatore perch permette di by-passare la restrizione (const)const int x = 12;int y = 10;int *p; puntatore-a-variabileconst int *q; puntatore-a-costantep = &x; Warning*p = 5; non d erroreq = &x; OK*p = 5; d errore

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 inizializzateint x, y;int * const p = &x; inizializzazione*p = 13; SI, *p una variabilep = &y; NO, p una costante

34

Esercizi1. Si scriva un programma che chieda una

stringa allutente e conti quanti siano i caratteri che la costituiscono, NON si usi la funzione strlen della libreria standard.

2. Scrivere un programma che verifichi se la stringa data in input palindroma o no

3. Scrivere un programma che chieda n valori interi (massimo 100), li collochi in un vettore e inverta il vettore (scambiando il primo elemento con l'ultimo, il secondo con il penultimo, 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 allutente 2 stringhe e concateni la seconda alla fine della prima, NON si usi la funzione strcatdella libreria standard, si usino i puntatori e non la notazione vettoriale. Attenzione a terminarla con il carattere \0.

7. Si scriva un programma che chieda allutente 2 stringhe e indichi se la seconda uguale alla parte terminale della prima.

36

Esercizi8. Scrivere un programma che chieda N valori

(massimo 100), li collochi in un vettore e li ordini in senso crescente (senza usare vettori ausiliari).

9. Scrivere un programma che verifichi se la stringa data composta di due parti uguali, trascurando il carattere centrale se la lunghezza dispari (es. CiaoCiao, CiaoXCiao).

10. Scrivere un programma che date 2 stringhe in input indichi quante volte la pi corta contenuta nella pi lunga.

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 allutente). Le righe si possono spezzare solo dove c uno spazio (che...

Recommended

View more >