Title: Puntatori e gestione dinamica della memoria
1Puntatori e gestione dinamica della memoria
- Corso di Informatica 2
- a.a. 2003/04
- Lezione 4
2Vantaggi nelluso dei vettori
- Sono legati allaccesso diretto agli elementi
utilizzando gli indici.
indirizzo vi b i ? d
d dimensione elemento
???
vi
v
b indirizzo base
i indice (spiazzamento)
3Indirizzamento della RAM
000
0
0
001
1
010
0
1
0
011
1
23
100
0
0
101
1
1
110
0
1
111
1
4Problemi nelluso dei vettori
- La dimensione di un vettore deve essere fissata
al momento della compilazione - int v100
- // non int vdim con dim variabile
- Linserimento di un nuovo valore comporta lo
slittamento di tutti quelli alla sua destra - for (j indice_prox_loc_libera j gt i j--)
- vj vj-1
- vi nuovo_valore
5I puntatori
- Un puntatore è una variabile il cui dominio di
definizione sono gli indirizzi di memoria - lttipogt ltvariabilegt
-
- int p // puntatore a intero
- int p, q
- // breve per int p int q
6Dereferenziazione ()
- Loperatore di dereferenziazione ( ltpuntatoregt)
legge/scrive alla locazione di memoria il cui
indirizzo è il valore del suo operando
p
025fe16
2983
025fe16
p 2983
7Operatore indirizzo ()
- Se x è una variabile, x è lindirizzo a cui
sono memorizzati i suoi valori
x
2983
025fe16
x 025fe16
8Esempio
// esempio di dereferenziazione e // uso
delloporatore include ltiostream.hgt int
main() int x 7 int p1, p2 // oppure
int p int q p1 x p2 p1 cout ltlt
p2 ltlt p2 ltlt endl // stampa il valore di
x cioe 7 cout ltlt p2 ltlt p2 ltlt endl //
stampa il valore di p2 cioe // lindirizzo di
x
9Condivisione (sharing)
I puntatori possono condividere larea di memoria
cui puntano int p, q int n 44 p q n
p
q
n
44
Ogni modifica del valore di n che avvenga per
assegnazione su p si riflette su n e su q.
Questa caratteristica viene sfruttata per
ottonere effetti collaterali sui valori dei
parametri attauli, passandoli cioè per indirizzo.
10Riferimenti
- In C si può avere sharing anche senza i
puntatori, usando riferimenti, ovvero sinonimi
(alias) - lttipogt ltnome rifgt ltnome vargt
int main () int n 44 int rn n // rn è
sinonimo di n n-- cout ltlt rn ltlt endl //
stampa 43
11Vettori e puntatori in C
- In C un vettore è una costante di tipo
puntatore - int v100 int p
- p v // il valore di p è lind. di base di v
- // ossia p v0
- Si può usare la notazione con gli indici per i
puntatori che si riferiscono a vettori - pi // equivale a vi
12Aritmetica dei puntatori (1)
- Ad ogni tipo di dato corrisponde la dimensione
in byte della memoria necessaria per contenere i
suoi valori - int sizeof(lttipogt) // C ritorna la dim.
- I puntatori sono tipati ciò è essenziale per
sapere cosa leggere/scrivere alle locazioni di
memoria cui puntano
13Aritmetica dei puntatori (2)
- In C si possono sommare (o sottrarre) interi a
puntatori - int p, q q p 10
- // il valore di q
- // valore di p 10sizeof(int)
- Quindi, se p punta ad un vettore v
- pi vi // ovvero
- (pi) vi pi
14Aritmetica dei puntatori (3)
- incremento e decremento int p p n p
- / p punta a n sizeof(int) /
- somma e sottrazione di un intero
- int n, m, p p n p p m
- / p punta a n m sizeof(int) /
- differenze tra puntatori
- int n, a, b, p, q p a, q b n p - q
- / n è il numero degli interi allocabili tra
- gli indirizzi di a e di b /
- confronto tra puntatori
- int n, m, p p n q m
- if (p lt q) / eseguito se lindirizzo di n
- è minore di quello di m /
15Esempio
void Inverti (int v int lun) // inverte
lordine degli el. di vlun int t, p,
q for(p v, q p (lun-1) p lt q p, q--)
t p p q q t
16Passaggio di parametri per valore
void f(int n) n
int a 0 f(a) cout ltlt a
17Passaggio di parametri per valore
void f(int n) n
int a 0 f(a) cout ltlt a
18Passaggio di parametri per valore
void f(int n) n
int a 0 f(a) cout ltlt a
0
a
1
n
19Passaggio di parametri per valore
void f(int n) n
int a 0 f(a) cout ltlt a
0
a
20Passaggio di par. per riferimento
void f(int n) n int a 0 f(a) cout ltlt a
21Passaggio di par. per riferimento
void f(int n) n int a 0 f(a) cout ltlt a
22Passaggio di par. per riferimento
void f(int n) n int a 0 f(a) cout ltlt a
23Passaggio di par. per riferimento
void f(int n) n int a 0 f(a) cout ltlt a
24Passaggio di par. per puntatore
void f(int pn) (pn) int a
0 f(a) cout ltlt a
25Passaggio di par. per puntatore
void f(int pn) (pn) int a
0 f(a) cout ltlt a
26Passaggio di par. per puntatore
void f(int pn) (pn) int a
0 f(a) cout ltlt a
27Passaggio di par. per puntatore
void f(int pn) (pn) int a
0 f(a) cout ltlt a
28Allocazione dinamica
- Allocazione destinazione di una certa quantità
di memoria per contenere valori di un dato tipo - Tutte le variabili di un programma sono allocate
quando sono in uso (puntatori inclusi) - E possibile allocare memoria durante
lesecuzione del programma in una area specifica
detta memoria dinamica
29Allocazione dinamica new
int p p new int p 2983
025fe16
30Allocazione dinamica new
int p p new int p 2983
p
025fe16
025fe16
31Allocazione dinamica new
int p p new int p 2983
p
025fe16
2983
025fe16
32Allocazione dinamica new
float p p 3.14159 // ERRORE p non è
allocato
33Allocazione dinamica in C
Tipo p p (Tipo) malloc (sizeof(Tipo)) Alloca
una struttura dati la cui dimensione in byte
dipende da Tipo ed è calcolata da sizeof in caso
di successo assegna il tipo Tipo allindirizzo
di inizio del blocco, ed il valore è salvato in
p. Se non cè più memoria disponibile, malloc
ritorna NULL, che sarà allora il valore di p.
34Allocazione dinamica di un vettore
- Per allocare dinamicamente un vettore occorre
conoscere - Il tipo dei suoi elementi
- il numero di questi elementi (che tuttavia potrà
essere noto anche solo al momento
dellesecuzione). - int v, lun
- v new intlun // in C
- v (int) malloc (sizeof(int)lun) // in C
- Alloca un vettore di lun interi, dove però lun è
una variabile. Comunque, una volta allocato, v
punterà ad un vettore la cui lunghezza non è più
modificabile.
35Le stringhe
- Le stringhe sono vettori di caratteri,
contenenti un terminatore \0 - char s Salve mondo
- char sMAXLUN
- char s Salve mondo
- Esiste un tipo stringa, definito
- typedef char String
36Allocazione di stringhe
- E opportuno costruire una funzione di
allocazione (allocatore o generatore) per ogni
struttura dati che si implementa -
- String StrAlloc(int len)
-
- String s
- s new Stringlen 1
- // len 1 per far posto a \0
- return s
-
37Operazioni sulle stringhe (1)
int strlen (String s) int n 0 while (s
! \0) n return n int strcpy (String
dest String source) while((dest
source)! \0)
38Operazione sulle stringhe (2)
String LeggiStringa (void) char bufferMAXLUN
String s gets(buffer) s Stralloc(strlen(buff
er)) strcpy(s, buffer) return s
39I record
Un record è una tupla di valori di tipi
possibilmente diversi acceduti attraverso
etichette
struct ltnome strutturagt lttipo1gt ltetichetta
campo1gt ... lttipokgt ltetichetta campokgt
40Allocazione dinamica di record (strutture)
- Come per i tipi di base e per i vettori, si
possono allocare record - typedef struct Record
- int field MyRecord
- MyRecord new Record
- Data la frequenza delluso di puntatori a
record, il C usa la sintassi - p-gtfield invece di (p).field
41Un modo per definire il tipo vettore (1)
- Un buon metodo per definire un vettore da
allocare dinamicamente è usare un record con un
campo lunghezza -
- typedef VecRec Vettore
- typedef struct vecrec
- int lun
- int vec
- VecRec
42Un modo per definire il tipo vettore (2)
v
n
????????????????
n elementi del vettore
43Un modo per definire il tipo vettore (3)
Vettore VettAlloc (int lunghezza) Vettore v
v new VecRec v-gtlun lunghezza v-gtvec
intlunghezza return v
44Un esempio più complesso matrici (1)
typedef MatrRec Matrice typedef struct matrmec
int righe, colonne int vecrighe MatrRec
n
m
?????
m
n
45Un esempio più complesso matrici (2)
Matrice NuovaMatrice (int r, int c) Matrice m
int i m new MatrRec m-gtrighe r
m-gtcolonne c m-gtvecrighe new intr
for (i 0 i lt r i) m-gtvecrighei
new intc return m
46Deallocazione
- La memoria dinamica allocata può essere
recuperata usando la funzione delete - delete ltpuntatoregt
- Per deallocare un vettore non occorre ricordarne
la dimensione - delete ltnome vettoregt
- Per deallocare una struttura complessa come
matrice occorrono tante chiamate di delete quante
sono state quelle di new
47Deallocazione di Matrice
void DeallocaMatrice (Matrice m) int i for(i
0 i lt m-gtrighe i) delete
m-gtvecrighei delete m-gtvecrighe delete
m