I Puntatori - Seconda Lezione
La caratteristica alla base dei puntatori è che con essi si
lavora su indirizzi di memoria, questo con il loro utilizzo comporta grandi
proprietà a vantaggio del programmatore ma anche alcune possibili problematiche
che potrebbero nascere dal loro utilizzo non appropriato: si potrebbe correre
il rischio di andare a modificare aree di memoria riservate ad altri processi
(ad esempio si potrebbe andare a modificare un area di memoria riservata al
sistema operativo il che potrebbe provocare blocchi o problemi di varia natura).
Proprio per questo motivo il compilatore esegue dei controlli prima di eseguire la compilazione del codice con puntatori.
Quando lavoriamo con tipi di dati primitivi
(int,float,char, ecc…) il compilatore non si pone particolari riserve e cerca
di fare quello che gli viene chiesto dalle istruzioni scritte dal programmatore, ma proprio per quanto detto poco fa quando si utilizzano i
puntatori invece il compilatore andrà ad eseguire una serie di controlli atti ad evitare un
utilizzo inappropriato.
*!* L’area di memoria valida di un puntatore è legata al
tipo di puntatore dichiarato (int, float, ecc…)
Vediamo alcuni esempi:
*!* La potenza dei puntatori sta nella possibilità di poter
allocare e successivamente liberare (quando non se ne ha più la necessità di
utilizzo) lo spaio di memoria allocato al puntatore stesso, cosa che non può invece
accadere con le variabili tradizionali (int, float, ecc…) che di conseguenza continuano a
mantenere memoria allocata anche qualora non fosse più necessario.
Vediamo alcuni esempi di Codice:
#include <iostream>
using namespace std;
int main()
{
int a=1;
int b=10;
int c;
cout<<"Inserisci un valore";
cin >> c;
if(c>5)
{
a++;
cout<<a;
}
else
{
b++;
cout<<b;
}
return 0;
}
In questo esempio la variabile contatore “a” o “b” viene
incrementata a seconda che il valore inserito dall’utente (contenuto nella
variabile “c”) sia o meno maggiore del valore 5. Ricollegandoci a quanto detto sopra possiamo vedere come in ogni caso, a prescindere dal valore dato
in Input dall’utente, il compilatore allocherà spazio nella memoria per tutte e
tre le variabili “a”, “b” e “c”.
Vediamo invece lo stesso esempio di codice scritto questa volta sfruttando le proprietà sopra elencate dei puntatori:
#include <iostream>
using namespace std;
int main()
{
int *a;
int *b;
int c;
cout<<"Inserisci un valore";
cin >> c;
if(c>5)
{
a=new int;
*a=1;
*a+=1;
cout<<*a;
delete a;
}
else
{
b=new int;
*b=10;
*b+=1;
cout<<*b;
delete b;
}
return 0;
}
#include <iostream>
using namespace std;
int main()
{
int *a;
int *b;
int c;
cout<<"Inserisci un valore";
cin >> c;
if(c>5)
{
a=new int;
*a=1;
*a+=1;
cout<<*a;
delete a;
}
else
{
b=new int;
*b=10;
*b+=1;
cout<<*b;
delete b;
}
return 0;
}
In questo esempio la variabile “a” e la variabile “b” sono
di tipo puntatore. Così facendo è possibile tramite l’istruzione “new int”
allocare spazio in memoria per la variabile puntatore sono al momento della necessità di utilizzo della variabile senza allocare spazio a prescindere, come succede con le viste
nell’esempio precedente, di conseguenza se l’utente inserirà un valore maggiore di 5
nella variabile “c” il programma allocherà memoria per il puntatore “a”,
assegnerà il valore 1 all’area di memoria da esso puntata, incrementerà tale
valore, visualizzerà “a” in Output e poi tramite l’istruzione delete libererà
lo spazio di memoria utilizzato dalla variabile puntatore “a” da li in poi non
più necessaria.
Lo stesso procedimento verrà eseguito per la variabile puntatore
“b” se il valore inserito in Input dall’utente sarà minore di 5.
Schema puntatore e indirizzi:
Schema logico di un doppio puntatore:
*!* In questo esempio la variabile puntatore “r” punta ad un
indirizzo che punta a sua volta ad un altro indirizzo che contiene un dato di
tipo intero.
Fonti:
Prof. Alemanno
Marchesi Giacomo
Nessun commento:
Posta un commento