Università dell’Insubria
Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese
Corso di Laurea in Informatica
Anno Accademico 2006/07
Laboratorio di Linguaggi
lezione V
Marco Tarini
Assegnare i Puntatori
• In memoria, un puntatore è un indirizzo di memoria
– (...di una variabile)
– (...di cui e' noto il tipo)
• Bene, ma quale indirizzo?
– Modo 1: prendere l'indirizzo di una variabile esistente
• il puntatore punterà a quella variabile
– Modo 2: allocare (riservare, prenotare) della memoria libera
• il puntatore punterà ad una nuova variabile, memorizzata nella
memoria così riservata
• la nuova variabile è allocata dinamicamente!
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione
void* malloc(unsigned int n);
funzione malloc ( sta per memory allocation )
1 - alloca n bytes di memoria.
2 - restituisce l' indirizzo della memoria appena allocata
• sotto forma di puntatore generico !
• " void* " puntatore generico,
puntatore senza tipo,
in pratica, un semplice indirizzo di memoria
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione: esempio
int* p;
p = malloc( ?
4 );
Errore di tipo!
A sx abbiamo un (int*) mentre a dx un (void*)
Il tipo è diverso, ma si tratta sempre di un indirizzo
di memoria!
Soluzione: basta fare un type-cast:
int* p;
p = (int*) malloc(4);
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione: e se la memoria finisce?
void* malloc(unsigned int n);
Se non c'è più memoria, l'allocazione "fallisce"
e malloc restituisce il valore speciale NULL
• semanticamente, NULL è un "puntatore che non punta a nulla"
• NULL è rappresentato dal valore
0
Il valore resituito dalle malloc va controllato !
int* p;
p = (int*) malloc(4);
if (p == NULL) {
/* finita memoria ... */
}
Marco Tarini ‧ Laboratorio di Linguaggi ‧
oppure,
più coincisamente
if (!p) {
2006/07 ‧ Università dell’Insubria
Allocazione
typedef struct {
/*blah blah... un sacco di campi, array...*/
} TipoStrano
TipoStrano* p;
p = (TipoStrano *) malloc(sizeof(TipoStrano));
Il costrutto sizeof è estremamente utile
con le malloc.
Usare sempre, anche con i tipi base
• int, short, float, double...
• remember: il C non prescrive quanti bytes occupano!
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Dellocazione
void free(void* p);
libera la memoria che era stata allocata all'indirizzo p.
Nota: p deve essere il risultato di una malloc!
int* p;
p = (int*) malloc(sizeof(int));
... /* Qui uso (*p) */
free(p);
se mi dimentico di deallocare, ho un cosiddetto memory leak
Remember: non c'è alcuna garbage collection in C !
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione e Deallocazione: esempio
k viene automaticamente allocato (i 4 bytes di
memoria necessari al suo immagazzinamento
vengono "prenotati").
int proc() {
int k;
k=15;
k viene inizializzato (a 15)
... /* lavora con k */
return 0;
all'uscita dalla procedura, i 4 bytes sono
resi di nuovo disponibili
};
k viene esplicitamente allocato. (a tempo di
esecuzione, si trovano i 4 bytes di memoria necessari
al suo immagazzinamento. La locazione viene
memorizzata in k).
k viene inizializzato (a 15)
all'uscita dalla procedura, dobbiamo
rendere i 4 bytes di nuovo disponibili
esplicitamente
Marco Tarini ‧ Laboratorio di Linguaggi ‧
usando l'allocazione dinamica:
int proc() {
int* k;
k = (int*)malloc(
sizeof(int)
);
*k = 15;
... /* lavora con *k */
free(k);
return 0;
};
2006/07 ‧ Università dell’Insubria
Vi ricordate di quell'altro problemino...
• Cosa succede, se non si sa a priori* quanti
elementi di un array ci serviranno**?
– * quando scriviamo il programma
– ** a tempo di esecuzione
• Necessità allocazione dinamica di array.
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione di vettori
(void*) calloc(unsigned int n, unsigned int size);
calloc = contiguous allocation
Alloca n elementi contigui ciascuno grande size.
In pratica, alloca un area di memoria grande n x size
Per il resto, funziona come malloc
Esempio:
int* p;
p = (int*) calloc(100000,sizeof(int) );
Alloca un vettore di 100000 interi.
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione di vettori
• Ricordiamoci sempre:
B) vettore allocato dinamicamente:
int* v = (int*) calloc(100000,sizeof(int) );
A) fixed size vector:
int v[100000];
• In entrambi i casi:
• ho un vettore di 100000 interi
• posso scrivere ad esempio:
v[2]= v[0] + 3 * v[1] ;
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione di vettori
• Ricordiamoci sempre:
B) vettore allocato dinamicamente:
int* v = (int*) calloc(100000,sizeof(int) );
A) fixed size vector:
int v[100000];
• Differenza 1: dimensione variabile
• se x è una var intera, posso scrivere:
int* v = (int*) calloc(x,sizeof(int) );
• ma non posso scrivere:
int v[x];
qua è richiesta una costante!
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione di vettori
• Ricordiamoci sempre:
B) vettore allocato dinamicamente:
int* v = (int*) calloc(100000,sizeof(int) );
A) fixed size vector:
int v[100000];
• Differenza 2: se ho allocato, devo deallocare
int* v = (int*) calloc(100000,sizeof(int) );
... /* usa v */
free(v);
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Allocazione di vettori
• Ricordiamoci sempre:
B) vettore allocato dinamicamente:
int* v = (int*) calloc(100000,sizeof(int) );
A) fixed size vector:
int v[100000];
• Differenza 3: fixed size = più efficiente
• il solito prezzo da pagare per l'uso dei puntatori...
0xAA000000 + 2 x sizeof(int)
• ...maggiorato
ma precalcolato staticamente
• mettiamo che v valga 0xAA000000 :
• se fixed size: v[2]
• se dinamco:
v[2]
compilazione
READ TEMP
compilazione
READ TEMP0
ADD TEMP0
READ TEMP
Marco Tarini ‧ Laboratorio di Linguaggi ‧
0xAA000008
0xAA000000
8
TEMP0
2006/07 ‧ Università dell’Insubria
Allocazione di vettori
• Ricordiamoci sempre:
B) vettore allocato dinamicamente:
int* v = (int*) calloc(100000,sizeof(int) );
A) fixed size vector:
int v[100000];
• Differenza 4:
• vengono allocati in zone diverse della memoria...
• come vedremo nella lezione sulla
gestione della memoria
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Puntatori: operazioni a basso livello
Esercizio:
un numero in
virgola mobile
a doppia precisione
di solito, ma dipende
dall'implementazione
• Sappiamo che un double occupa 8 bytes.
• Dato un double, quale è il valore di questi 8
bytes?
• Per esempio, quali 8 bytes compongono il
valore 3.14159256 ?
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Puntatori: operazioni a basso livello
1B903C32
1B903C33
1B903C34
1B903C35
1B903C36
1B903C37
1B903C38
1B903C39
1B903C3A
1B903C3B
1B903C3C
spazio riservato per la variabile d (8 bytes)
int main()
{
dobule d;
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Puntatori: operazioni a basso livello
1B903C32
1B903C33
1B903C34
1B903C35
1B903C36
1B903C37
1B903C38
1B903C39
1B903C3A
1B903C3B
1B903C3C
codifica di 3.14159256
spazio riservato per la variabile d (8 bytes)
un puntatore a
Byte che farà
da vettore di
Bytes
ma il tipo "Byte"
non è definito!
Definirlo, ad es
fuori dalla proc
"main" (vedere
lez. 2)
int main()
{
dobule d;
d = 3.14159256;
Byte * v ;
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Puntatori: operazioni a basso livello
1B903C32
1B903C33
1B903C34
1B903C35
1B903C36
1B903C37
1B903C38
1B903C39
1B903C3A
1B903C3B
1B903C3C
vc[0]o dv[1]
v[6]2 5v6
[7]
i f i vc[2]a dv[3]
i 3v.[4]1 4v[5]
159
spazio riservato per la variabile d (8 bytes)
int main()
{
dobule d; int i;
d = 3.14159256;
Byte * v ;
v = &
(Byte*)
d;
& d;
for (i=0; i<
i<8;
sizeof(double);
i++)
i++)
printf("%d,",v[i]);
};
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Puntatori: operazioni a basso livello
• A casa, provate questo programma, e scopriamo:
– quali sono gli 8 bytes che compongono il double 3.14159256
– quali sono gli 8 bytes che compongono il double 6.022 x 1023
• e, adattando il programma agli interi:
– quali sono i 4 bytes che compongono l'int +1000000
– quali sono i 4 bytes che compongono l'int +1
– quali sono i 4 bytes che compongono l'int -1
• a seconda di quale architettura viene usata, potremmo
trovare risposte diverse!
– domanda: sarebbe potuto succedere in Java?
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Ricapitoliamo: uso dei puntatori
• Molto potenti...
– vettori di dimensione determinata dinamicamente
– passaggio di parametri per riferimento
• in un linguaggio che prevede passaggio solo per copia
– possibilità di scrivere codici più efficienti
– controllo diretto delle risorse, a basso livello
– strutture dati flessibili
• per esempio:
typedef struct {
char nome[20];
char cognome[20];
int eta;
Persona* padre, madre;
} Persona;
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Puntatori
• Molto potenti...
"Ad un grande potere corrisponde una
grande responsabilità."
– lo zio di Spiderman
Marco Tarini ‧ Laboratorio di Linguaggi ‧
2006/07 ‧ Università dell’Insubria
Scarica

ppt