PUNTATORI
riferimento
= un riferimento è la costante NULL oppure l'indirizzo di una
variabile del tipo T (tipo base; un qualsiasi tipo)
<tipo referente>
*<identificatore>;
es.
int
*p;
attento: l'operatore
“*” si associa con l'identificatore non con il nome di
tipo:
scrivi “int *p”,
non “int* p”
int
*p, *q; p e q puntatori
int
*p, q; solo p puntatore, q intero
int
*p, q; idem
“&”
(che non potrà mai stare a sinistra di un operatore di
assegnamento: es. &v = ....) applicato a un designatore mi
restituisce l'indirizzo della variabile designata
“*” =
operatore di deferenziazione = applicato ad una espressione di tipo
T* (indirizzo di variabile di tipo T) restituisce la variabile che ha
quell'indirizzo (sempre che
l'espressione abbia valore diverso da NULL)
quando dichiaro un
puntatore senza inizializzarlo con un indirizzo, questo punta a una
cella di memoria qualsiasi (molto pericoloso)
int
*p;
int
q;
q
= 5;
p
= &q;
*p
(è un designatore perchè mi restituisce una variabile
quindi può stare a sinistra in un comando di assegnamento; es.
*p = 4; assegna alla variabile puntata da p il valore 4)
&p
mi restituisce una variabile di tipo puntatore a puntatore
es.
void
scambia(int a, int b){
int
temp;
temp
= a;
a
= b;
b
= temp;
}
int
main(){
int
x, y;
x
= 0;
y
= 4;
scambia(x,y);
return
0;
}
non funziona perchè
non va a toccare le variabili x e y ma solo quelle locali a e b
es. corretto:
void
scambia(int *a, int *b){
int
temp;
temp
= *a;
*a
= *b;
*b
= temp;
}
int
main(){
int
x, y;
x
= 0;
y
= 4;
scambia(&x,
&y);
return
0;
}
il valore restituito
come funzione può essere solo uno ma posso utilizzare i
puntatori per ovviare a questo problema
double
somma_media(int a, int b, int c, int *k){
*k
= a + b + c;
return
(*k)/ (double) 3;
}
int
main(){
int
a,b,c,somma;
double
media;
a
=
b
=
c
=
somma
= somma_media(a,b,c,&media);
}
ARITMETICA DEI PUNTATORI
l'operazione di
addizione nell'aritmetica dei puntatori incrementa il puntatore in
base al suo tipo base: incrementare di 1 un puntatore significa far
saltare il puntatore alla prossima locazione corrispondente ad un
elemento di memoria il cui tipo coincide con quello base;
se p è
l'indirizzo di una variabile di tipo tabella di T (tipo base), ossia
p = &Tab[0], allora p + i, dove i è una costante intera, è
per definizione &Tab[i]
es.
int
tab[2]=...
int
*q = tab; //punta a tab[0], manca & perchè tab è
un array
q++;
//ora q punta a tab[1], in termini di indirizzi passo ad esempio da
8000 a 8004 (perchè 4 di differenza? perchè la memoria
viene indirizzata al byte)
la scrittura:
*q++
è da evitare;
chi ha la precedenza ? l'operatore ++, quindi è equivalente a:
*(q++)
se abbiamo p e q di
tipo T* che puntano ad indirizzi di celle di una stessa tabella (di
tipo base T):
p
= &tab[h]
q
= &tab[k]
q
– p = (&tab[k] - &tab[h])/sizeof(T))
sizeof(T) è la
dimensione del tipo
OPERAZIONI FRA PUNTATORI:
la somma tra due
puntatori non è definita
la sottrazione tra
due puntatori è definita e ha significato solo se entrambi
puntano ad un elemento dello stesso array (se sottraggo ottengo il
delta tra i due elementi nell'array)
SIZEOF
printf(“%d”,
sizeof(int));
stampa il numero di bit
che mi serve per rappresentare una variabile di tipo intero
la posso applicare
anche a specifiche variabili:
printf(“%d”,
sizeof(int s));
ARRAY MULTIDIMENSIONALI
es.
int
tab[3][3];
alloca 9 celle contigue
di memoria
|
AMBIENTE
|
|
MEMORIA
|
|
|
int *tab
|
------>
|
colonna 1
|
riga
|
|
|
|
colonna 2
|
1
|
|
|
|
colonna 3
|
|
|
|
|
colonna 4
|
riga
|
|
|
|
colonna 5
|
2
|
|
|
|
colonna 6
|
|
|
|
|
colonna 7
|
riga
|
|
|
|
colonna 8
|
3
|
|
|
|
colonna 9
|
|
|
|
|
|
|
le seguenti scritture
sono tutte equivalenti a tab[1][2]:
*(&tab[1]
+ 2)
(*(tab
+ 1))[2]
*(&tab[0][0]
+ (3*1) + 2)
in C esistono solo
tabelle monodimensionali
a[k][h]
di tipo T
a[k]
è di tipo T*
a
è di tipo T**
Q a[k] a è di
tipo Q*
T* a[k] a è di
tipo T**
int
*p
int
a[4]
posso scrivere
p
= a;
ma non
a
= p
poiché a non è
una variabile
l'unica maniera per
”clonare” un array è utilizzare un ciclo for
funzione che calcola la
somma degli elementi di un array
int
somma(int k[], int dim){
int
i;
int
somma = 0;
for
(i = 0;i < dim; i++)
somma
+= k[i];
return
somma;
}
ricorsiva:
int
somma(int k[], int dim){
if
(dim = 0) return 0;
else
return
k[0] + somma(k + 1, dim – 1);
}
|