Ora che conosciamo la struttura “a cassetti” della memoria e come viene organizzata a tempo di esecuzione possimo introdurre il concetto dei puntatori (o riferimenti).
Questo tipo di variabili sono ben noti a chi programma in C ma esistono in modo meno diretto in decine di linguaggi, come il Java, tanto per dirne qualcuno.
Il concetto espresso dai puntatori è mio avviso semplice anche se poi finisce per complicare la vita a molti. Quindi spero di trasmettervi questa “semplicità” con cui riesco a navigare io nel mare dei riferimenti.
Abbiamo visto che una variabile non è altro che un nome mnemonico per individuare il cassetto in cui sono infilati i dati ad essa associati.
Un puntatore, invece, si basa su un altro concetto seppur molto simile. Esso è infatti un nome mnemonico per individuare l’indirizzo del cassetto in cui sono contenuti i dati. Sono quindi variabili che contengono l’indirizzo di una variabile.
Come vedete la differenza è sottile ma allo stesso tempo sostanziale. Un puntatore quindi non contiene il dato ma l’indirizzo in cui è contenuto il dato. Il dato in questione può essere un qualunque dato e persino un altro puntatore.
Perché utilizzare l’indirizzo e complicarsi la vita quando invece potremmo usare direttamente una variabile?
Semplice. Le motivazioni sono fondamentalmente due: a volte è necessario, a volte è dannatamente comodo.
Abbiamo visto infatti nella scorsa lezione delle limitazioni in cui incorrono le variabili, in particolare le variabili di una funzione. Esse sono infatti statiche e locali.
Queste due forti limitazioni possono essere superate grazie ai puntatori. Cominciamo dalla località.
Supponiamo che la funzione XYZ chiami la funzione ABC e vogliamo che ABC abbia come risultato quello di modificare tre variabili locali di XYZ. Proviamo quindi a passare come parametri di ABC le tre variabili. Le modifichiamo con ABC e poi torniamo in XYZ…. sorpresa! Le variabili non sono cambiate!
Perchè? E’ semplice. Come abbiamo detto in precedenza quando viene invocata una funzione si prende un nuovo “block notes” in pila e si copiano delle informazioni della funzione chiamante ma soprattutto si copiano i valori dei parametri.
E’ questo il punto! In ABC non abbiamo le variabili originarie ma copie e qualunque modifica la faremo su queste copie (che verranno inesorabilmente distrutte non appena la funzione ritornerà).
Allora come fare? Ovvio, passando i puntatori alle tre variabili da modificare come parametro di ABC. In questo modo ABC avrà una copia dell’indirizzo in cui sono le 3 variabili. Ma l’indirizzo punta esattamente all’indirizzo delle variabili di XYZ!! Quindi qualunque modifica si riperquoterà anche sulle variabili di XYZ perchè in realtà sono la stessa variabile.
Questa gestione dei puntatori però è propria di quei linguaggi di medio-alto livello come C ed è difficile trovare altri linguaggi che permettano un cosi capillare uso dei puntatori.
I puntatori sono invece necessari quando trattiamo oggetti dinamici.
Gli indirizzi di memoria hanno il vantaggio di essere sempre statici (un indirizzo ha sempre 32bit). Quindi se una variabile non riesce a trattare gli oggetti dinamici ci riesce benissimo il puntatore poichè in realtà lui lavora con l’indirizzo in cui comincia l’oggetto dinamico.
Quindi qualunque oggetto dinamico viene rappresentato sempre con un puntatore. Anche gli oggetti in Java sono in realtà puntatori. Oppure le liste in python. Tutti gli oggetti dinamici vengono trattati come puntatori.
Sebbene possiate scordarvi del primo esempio a meno che non vogliate scrivere in C, non potete assolutamente scordarvi quest’ultimo concetto in quanto ve lo ritroverete fra i piedi in ogni linguaggio.
Concludo con un esempio e una considerazione che spero chiarisca l’idea e vi faccia notare quanto è naturale il concetto dei puntatori.
Nella vita di tutti i giorni usiamo i riferimenti per tutto: quando parliamo di un libro diciamo il suo titolo il quale non è altro che un riferimento al libro in se. Se io cambio il titolo non è che si modifica il libro… semplicemente mi riferisco ad un altro libro (che può anche non esistere). Quando voglio indicare casa mia dico il suo indirizzo. Se io dico un altro indirizzo non è che si sposta la casa… semplicemente penso ad un altra casa.
Vabbè. Deliri. A me questa cosa aiutò 🙂
Mi piacciono le ultime metafore, penso le riutilizzero’ spiegando a qualcuno i puntatori :°D
Complimenti, continua cosi’ 😉