• Non ci sono risultati.

operatore di indirizzo & &

N/A
N/A
Protected

Academic year: 2022

Condividi "operatore di indirizzo & &"

Copied!
32
0
0

Testo completo

(1)

I

PUNTATORI

(2)

P

UNTATORE

È una variabile che contiene l’indirizzo di memoria di un oggetto (variabile o costante)

Esempio

p è un puntatore e “punta” alla variabile x che in questo esempio ha indirizzo di memoria A55

(3)

D

EFINIZIONE

Sintassi

tipo *nomeVariabile;

Esempi

int *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)

A

SSEGNAZIONE

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

L’operatore di indirizzo ‘&’ (“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 x p = &y; assegna a p l’indirizzo di y

(5)

U

TILIZZO

Si accede all’oggetto puntato da un puntatore per mezzo dell’operatore ‘*’ detto operatore 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 è l’oggetto puntato (qui è x)

Si noti che la sintassi per indicare l’oggetto

puntato e quella della definizione del puntatore sono identiche: *p

(6)

U

TILIZZO

Sia p sia *p sono L-value modificabili, ossia sono un “qualcosa” (variabile, elemento di vettore, …) a cui si può assegnare un valore

L’operatore ‘*’ ha priorità superiore a quella degli operatori matematici

x = 6 * *p; equivale a: x = 6 * (*p);

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

(7)

T

IPI E PUNTATORI

L’informazione relativa al tipo è necessaria per permettere ai puntatori di conoscere la

dimensione dell’oggetto puntato (usata nell’aritmetica dei puntatori)

Poiché oggetti di tipo diverso possono avere

dimensione diversa, l’assegnazione tra puntatori di tipo diverso è in genere errata e il compilatore genera un warning

(8)

P

UNTATORI 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 (a qualsiasi tipo)

void *h;

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

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

NULL è definito come: (void *)0

(9)

P

UNTATORI 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 dell’oggetto puntato

Può essere necessario il cast (tipo *) per copiare un puntatore void in un puntatore non-void

(10)

P

UNTATORI A VOID

In riferimento all’esempio precedente:

int *q;

q = h; - OK, compilatore C

q = (int *)h; - OK, compilatore C++

*q = 23; - x ora contiene 23

(11)

P

UNTATORI 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 primo elemento di

vettore

int vett[100];

int *p;

p = vett;

l’indirizzo di memoria di vett viene messo in p, equivale a scrivere: p = &vett[0] (le parentesi hanno priorità maggiore di &)

(12)

P

UNTATORI 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 memoria

Gli indirizzi di memoria sono valori costanti stabiliti dal compilatore, non sono variabili e quindi non hanno uno spazio in memoria

modificabile per contenere un valore

Il termine “puntatore” viene comunemente (e impropriamente) usato al posto di “indirizzo di memoria” (es. “&a dà il puntatore ad a”)

(13)

E

QUIVALENZA PUNTATORI E VETTORI

Una variabile di tipo puntatore-a-T, assegnata in modo che punti a (cioè contenga l’indirizzo di) 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 le espressioni con notazione vettoriale [ ] in espressioni con i puntatori

(14)

A

RITMETICA DEI PUNTATORI

Quando un puntatore punta ad un vettore, gli può essere sommato un valore intero N, il

risultato è l’indirizzo di memoria dell’elemento di posizione N del vettore

p punta a (contiene l'indirizzo di) vett p+3 punta a (produce l'indir. di) vett[3]

*(p+3) equivale a vett[3]

(15)

A

RITMETICA DEI PUNTATORI

L’istruzione p++ porta p a puntare a vett[1]

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

È lecito sottrarre un valore N ad un puntatore se l’elemento puntato risultante fa ancora parte del vettore (nell’esempio precedente p-1 punta a

vett[0])

(16)

E

QUIVALENZA 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]

(17)

E

QUIVALENZA PUNTATORI E VETTORI

Senza il decadimento, vett+1 punterebbe al primo byte dopo la fine di vett

Eccezioni:

vett in un sizeof non decade e per questo dà la dimensione dell’intero vettore, non

quella del primo elemento

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

vettore-di-int

(18)

E

QUIVALENZA 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 il programmatore e sta a questi utilizzarlo in modo coerente

int x = 10, vett[10], *p, *q;

p = &x;

p++; NO! Non esiste l’oggetto puntato da p+1 q = p+1; NO! Idem

p = vett;

p++; SI’! Ora p punta a vett[1]

q = p+1; SI’! Ora q punta a vett[2]

(19)

A

RITMETICA 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)

È lecito che un puntatore punti a quello che sarebbe l’elemento del vettore successivo all’ultimo, ma questo puntatore può essere utilizzato solo per calcolare la differenza tra puntatori

(20)

A

RITMETICA 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 alla posizione 10 inclusi

Due puntatori possono essere confrontati solo se fanno parte dello stesso vettore oppure uno dei due è NULL

(21)

P

RIORITÀ DELL

OPERATORE

*

Dalla tabella delle priorità si vede che l’operatore di deriferimento * ha priorità quasi massima,

inferiore solo alle parentesi, 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)

(22)

C

OPIA DI STRINGHE

: 1

A VERSIONE

(23)

C

OPIA DI STRINGHE

: 2

A VERSIONE

(24)

C

OPIA DI STRINGHE

: 3

A VERSIONE

(25)

C

OPIA DI STRINGHE

: 4

A VERSIONE

(26)

P

UNTATORI 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

(27)

P

UNTATORI E STRINGHE

Si noti la differenza tra le seguenti definizioni:

char *s;

NON RISERVA spazio per contenere i caratteri, quindi per essere utilizzata come stringa le si deve assegnare una stringa “vera”:

o Assegnazione di una stringa variabile:

s = str;

scanf("%s", s); - SI’

o Assegnazione di una stringa costante:

s = "salve";

scanf("%s", s); - NO

(28)

P

UNTATORI E STRINGHE

Si considerino i seguenti esempi:

char str[] = "ciao";

È l’inizializzazione 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’

(29)

P

UNTATORI E STRINGHE

Si considerino i seguenti esempi:

char *s = "hello";

È l’inizializzazione di una variabile puntatore:

il compilatore determina l’indirizzo della stringa

costante "hello" (che esiste in memoria) e lo assegna alla variabile puntatore s

s[0]='b'; - NO! "hello" è costante!

(30)

P

UNTATORI E STRINGHE

Si considerino i seguenti esempi (cont.):

s = "salve";

È l’assegnazione ad una variabile puntatore:

il compilatore determina l’indirizzo della stringa costante "salve" (che esiste in memoria) e lo

assegna alla variabile puntatore s

s[4]='o'; - NO! "salve" è costante!

(31)

P

UNTATORI E STRINGHE

Si considerino i seguenti esempi (cont.):

s = str;

È l’assegnazione ad una variabile puntatore:

il compilatore determina l’indirizzo della stringa variabile str (che esiste in memoria) e lo assegna alla variabile puntatore s

s[0]='m'; - SI’

(32)

P

UNTATORI 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 all’oggetto cercato o NULL se non lo trovano

Riferimenti

Documenti correlati

[r]

Generalmente il confronto può essere fatto tra due generici puntatori che puntano allo stesso tipo di dato; questo confronto è comunque significativo solo nel caso in

We apply this method to a temporal series of large FoV MDI (Michelson Doppler Imager) magnetograms, to identify voids be- tween magnetic structures and to extract their normalized

(Febbraio 2012); secondo gli studiosi americani, l’efficienza energetica è si il primo degli strumenti per mitigare i cam- biamenti in atto attraverso la riduzione del consumo di

■ Quindi il vero argomento della prima funzione non é la seconda funzione, ma un normale valore, che può avere qualsiasi origine (variabile, espressione ecc...), e in particolare

In questo caso si ritiene che tutti gli aspetti e le modalità di realizzazione del servizio possano essere definiti con precisione dalla stazione appaltante sulla base delle

Member(E, lista): verifica se l’elemento E è presente nella lista Append(E, lista): inserisce l’elemento dato E in coda alla lista (due. versioni: nella prima versione uso di

- Assumere la doxiciclina per tutta la durata stabilita della terapia (l’assunzione irregolare può anche aumentare il rischio di infezione creando resistenze agli antibiotici);. -