Puntatori e gestione
dinamica della RAM
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Limiti della allocazione statica (array)
1 - SPAZIO ALLOCATO FISSO
(gestione non ottimale RAM)
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Limiti della allocazione statica della RAM (array)
1 - GESTIONE NON OTTIMALE DELLA RAM
Per alcuni programmi la quantità di RAM
effettivamente utilizzata è MOLTO variabile
Autocad, Word, PhotoShop, Excel …
Usando gli array il programmatore non avrebbe
altra possibilità che stare ‘largo’:
dimensionarli pensando al caso peggiore
(massima richiesta RAM)
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Limiti della allocazione statica della RAM (array)
1 – GESTIONE NON OTTIMALE DELLA RAM
Ma questo in ambienti multitask o multiutente
significherebbe allocare molta più ram
di quella necessaria
=
Minor numero di programmi che il sistema sarebbe
in grado di gestire in contemporanea
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Limiti della allocazione statica della RAM (array)
1 – GESTIONE NON OTTIMALE DELLA RAM
Soluzione
Un meccanismo per allocare in un certo istante
esattamente la quantità di memoria che serve e per
restituirla al sistema quando non serve più
=
puntatori + malloc() + sizeof() + free()
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
malloc() – memory allocation
malloc(numero_byte_richiesti)
Chiede al s.o. uno spazio contiguo di byte
Se la richiesta viene soddisfatta viene restituito l’indirizzo di
inizio del blocco ‘prenotato’ (problema: dove memorizzarlo?)
NB: se non c’è abbastanza memoria
malloc() restituisce null
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
0
1
2
3
…
malloc(1000)
Il sistema trova spazio a partire dall’indirizzo 0x19AF2
1000 byte
riservati!
Per scrivere e leggere in questi 1000 byte il programmatore
ha bisogno di memorizzare l’indirizzo in una variabile.
int, float e double non vanno bene
Esiste il tipo apposito reference (puntatore)
RAM
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
0x19AF2
char* pChar;
0
1
2
3
…
pChar (o un qualsiasi altro nome di
variabile) viene in questo modo definita
1000 byte
riservati!
come un puntatore a char.
Più correttamente dovremmo
inizializzarla: char* pChar = NULL;
RAM
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
0x19AF2
char* pChar=NULL;
E’ molto importante che un puntatore
0
1
2
3
…
che al momento non sta individuando
0x19AF2
nessun blocco di memoria abbia il
1000 byte
riservati!
valore NULL. Consente un uso sicuro:
if (pChar) //se valido …
RAM
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
char* pChar=NULL;
0
1
2
3
…
Situazione prima di aver memorizzato
un indirizzo valido in pChar:
pChar
NULL
RAM
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
char* pChar=NULL;
pChar = (char*) malloc (1000);
*pChar
1000 byte
riservati!
Situazione dopo aver memorizzato un
indirizzo valido in pChar:
pChar
RAM
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
0
1
2
3
…
0x19AF2
pChar = (char*) malloc(1000);
?
0
1
2
3
…
malloc() ‘non sa’ che tipo di valori
verranno memorizzati nel blocco che ha
riservato. Il valore restituito è quindi un
1000 byte
riservati!
puntatore ‘generico’ che va bene per
qualsiasi cosa. E’ poi il programma che
deve specificare come usare il blocco: per
char? int? float? una struct?
RAM
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
0x19AF2
pChar = (char*) malloc(1000);
… utilizzo della memoria …
0
1
2
3
…
free(pChar);
pChar = NULL;
free restituisce al s.o. il blocco di RAM
ed è molto importante marchiare il
puntatore come non più valido (NULL)
RAM
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Utilizzo della RAM allocata
0
1
2
3
…
Iniziamo con un caso ancora più semplice:
char* pChar = (char*) malloc(1);
0x19AF2
lo spazio in RAM è sufficiente esattamente per un carattere
‘A’
Come memorizzare ‘A’ in quello spazio?
errore classico: pChar = ‘A’;
Ci si sta dimenticando che pChar non è una variabile char
ma l’indirizzo della variabile char! Un puntatore.
CORRETTO
*pChar = ‘A’
prof. Fabrizio Camuso – www.camuso.it
RAM
versione 1.0 Gennaio 2012
Utilizzo della RAM allocata
*puntatore
0
1
2
3
…
fa passare dall’indirizzo all’area
puntata dall’indirizzo
0x19AF2
‘A’
cout << “Dammi un carattere”;
cin >> *pChar;
cout << “Hai inserito “ << *pchar;
Insomma, basta ricordarsi nell’uso di
mettere davanti sempre l’asterisco…
prof. Fabrizio Camuso – www.camuso.it
RAM
versione 1.0 Gennaio 2012
Utilizzo della RAM allocata
questo rende evidente la differenza!
char* pChar = (char*) malloc(1);
*pChar = ‘A’;
cout << “Indirizzo: “ << pChar << endl;
cout << “Oggetto puntato: “ << *pChar << endl;
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a tipi semplici (int, float ecc.)
sizeof(TIPO)
p = (int *) malloc( sizeof(int) );
*p = 123;
Allo stesso modo si
procederebbe con float,
double, bool.
Ma NON con string
cout << “ - valore: “ << *p;
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a tipi semplici
sizeof(TIPO)
cout << sizeof(char) << endl;
cout << sizeof(int) << endl;
cout << sizeof(float) << endl;
cout << sizeof(double) << endl;
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a VETTORI
Un vettore di 1000 interi
p = (int *) malloc( 1000 * sizeof(int) );
E poi come lo usiamo?
*p = 10; //lo accetta? cosa fa??
p
10
prof. Fabrizio Camuso – www.camuso.it
E questi ??
versione 1.0 Gennaio 2012
Puntatori a VETTORI
Un vettore di 1000 interi
p = (int *) malloc( 1000 * sizeof(int) );
p[0] = 10; //!! interessante !!
DUALITA’ puntatori/vettori
*p equivale a p[0]
p
10
E questi ??
*p oppure p[0]
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a VETTORI
Ah, beh allora ….
p = (int *) malloc( 1000 * sizeof(int) );
p[0] = 10; //!! interessante !!
p[1] = -5;
p[2] = …
Insomma: dichiarazione a parte poi si fa
come al solito!! Cicli compresi.
10 -5 …
p[0]
p[1]
…
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a VETTORI
Ultima cosa speciale da sapere: i puntatori si
possono incrementare ed il risultato è che si spostano
in avanti a puntare gli elementi successivi
p = (int *) malloc( 1000 * sizeof(int) );
*p = 10;
*(p+1) = -5;
*(p+2) = …
In alcune situazioni torna comodo …
10 -5 …
*p
*(p+1)
…
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a VETTORI
Si può anche modificare in modo permanente il
valore ma bisogna stare attenti!
p = (int *) malloc( 1000 * sizeof(int) );
*p = 10; p++;
*p = -5; p++;
*p = …
Abbiamo perso l’indirizzo di inizio del vettore!
10 -5 …
p
prof. Fabrizio Camuso – www.camuso.it
???
versione 1.0 Gennaio 2012
Puntatori a VETTORI
Meglio farlo con una variabile ausiliaria:
p = (int *) malloc( 1000 * sizeof(int) );
int* temp = p; //temp è una copia di p
*temp = 10; temp++;
*temp = -5; temp++;
*temp = …
p
p è rimasto ‘al sicuro’
10 -5 …
temp
temp++
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a STRUCT
Le motivazioni addotte per i vettori di variabili
semplici valgono, a maggior ragione,
per i vettori di struct.
Infatti una struct occupa più memoria di
una variabile non strutturata .
La cattiva gestione che ne conseguirebbe con un uso
statico è quindi potenzialmente molto maggiore.
Ma c’è un altro motivo …
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a STRUCT
Applicazione6
Applicazione1
Sistema Operativo
(o altro modulo sw che fornisce servizi)
risposta
(return …)
Applicazione2
richiesta
Applicazione3
temp
prof. Fabrizio Camuso – www.camuso.it
Applicazione5
Applicazione4
Informazioni
struct creata
al momento
distrutta quando
non serve più
versione 1.0 Gennaio 2012
MOLTE!!
Puntatori a STRUCT
struct poesie {
char poeta[40];
char titolo[100];
int anno; }
Importante: per creare dinamicamente le struct non
possiamo usare il tipo string ma vettori di caratteri; a
parte questo rimangono disponibili i soliti meccanismi
di input/output con cin e cout:
cin/cout riferimento_alla_struct.poeta
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a STRUCT
struct poesie {
char poeta[40];
char titolo[100];
int anno; }
p = (poesie *) malloc( sizeof(poesie) );
tutto molto logico visto che si vuole un
puntatore ad un oggetto di tipo poesie e
creare spazio per un oggetto dello stesso
tipo…
e l’utilizzo del puntatore ?
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a STRUCT
Dobbiamo combinare l’uso del punto tipico dell’accesso alle variabili delle strutture
con l’uso dell’asterisco tipico dei puntatori:
struct poesie {
char poeta[40];
char titolo[100];
int anno; }
p = (poesie *) malloc( sizeof(poesie) );
(*p).anno = 2005;
Le parentesi in (*p) servono perchè altrimenti p. verrebbe
trattato come una struct invece di un puntatore a struct.
(*p) fa passare dal puntatore all’oggetto puntato, la struct;
solo dopo questo passaggio si può usare il punto
però …
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a STRUCT
I progettisti del linguaggio si sono resi conto che la doppia
sintassi è veramente pesante, tenuto anche in considerazione
che l’uso di puntatori a struct è diffusissimo.
Quindi … semplificazione!
non solo
(*p).anno = 2005;
ma anche
p->anno = 2005;
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Puntatori a STRUCT
Per i vettori di struct creati dinamicamente invece ci sono
meno problemi:
poesie* pPoesieVett = (poesie*) malloc(100 * sizeof(poesie) );
pPoe[4].anno = 2134;
o anche:
(*(p+4)).anno = 1234; //pesante …
(p+4)->anno = 1234; //decisamente meglio!
-> tratta in automatico l’espressione a sinistra come un
puntatore a struttura e
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Dai sorgenti di Doom3 …
void Save( idSaveGame *savefile )
{ …savefile->WriteInt( travelFlags ); … }
La funzione Save riceve un puntatore (savefile) ad un oggetto
idSaveGame, una struct che rappresenta il file su cui salvare il
gioco.
Con la OOP, che vedremo, una struct può anche contenere funzioni
oltre che variabili.
Con savefile->WriteInt(…) si sta richiamando il comando
WriteInt(…) della struct puntata dal puntatore savefile
temp
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Dal sorgente consigliato da Google
per usare Maps sui vostri siti con PHP
…
function GoogleMapAPI($map_id = 'map', $app_id = 'MyMapApp')
{
$this->map_id = $map_id;
$this->sidebar_id = 'sidebar_' . $map_id;
$this->app_id = $app_id;
}
Ora sapete cosa si sta facendo: $this è un puntatore ad oggetto (nella OOP si
parla di classi e oggetti al posto di struct e variabili ma è lo stesso concetto) che
contiene la variabile map_id.
… vuoi vedere che anche per programmare con … servono queste cose??
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Un esempio di uso di FaceBook
sui vostri siti, sempre con PHP
class manage
{
private $entryId;
function __construct($entryId)
{
$this->entryId = $entryId;
}
}…
Memoria dinamica, puntatori a struct (oggetti) e OOP servono per tutte
le cose più interessanti della programmazione WEB o non WEB.
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Limiti della allocazione statica (array)
2a – molto poco efficiente
per operazioni di inserimento
a b c e f g h i j k l mn o p q r s t u v z
spazio libero
d
parte del vettore da spostare (shift a destra)
a b c d e f g h i j k l mn o p q r s t u v z
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Limiti della allocazione statica (array)
2b – molto poco efficiente
per operazioni di cancellazione
a b c d e f g h i j k l mn o p q r s t u v z
spazio libero
parte del vettore da spostare (shift a sinistra)
a b c e f g h i j k l mn o p q r s t u v z
prof. Fabrizio Camuso – www.camuso.it
versione 1.0 Gennaio 2012
Scarica

(*p).