Programmazione – Lezione 9 – I puntatori

puntatori

Una peculiarità del linguaggio C è data dal’uso dei puntatori. L’uso corretto ed il concetto in se non è semplice da spiegare e da capire, ma tale linguaggio ne fa un grande uso per cui mi sembra corretto fare dei cenni, anche perché li utilizzeremo spesso, non potendone fare a meno. Se ne farà un uso massiccio nel linguaggio Objective-C di cui vorrei parlarvi tra qualche articolo.

Cercherò di farmi capire, almeno spero.

Come accennai all’inizio, la CPU memorizza le nostre variabili in aree di memoria ben specifiche in base al tipo di dato da memorizzare, char, int, float, double, e alla sua lunghezza, quindi viene assegnato uno spazio specifico in un area di memoria. Per accedere a quest’area la CPU ricorre ad un indirizzo, chiamato indirizzo di memoria. Questo indirizzo è espresso, per convenzione, in esadecimale. In realtà la CPU opera sempre e solo con i numeri binari ma per noi scrivere tali numeri in binario risulterebbe spesso scomodo e troppo lungo.

Facciamo un esempio, consideriamo il numero decimale 1456.

Decimale: 1456

Binario: 10110110000

Esadecimale:5B0

Come vedete, anche se la CPU, lavora in binario, scrivere 1456 in binario richiede 11 caratteri (e la CPU lavora così), mentre in esadeciamle nebastano appena 3.

Ritorniamo agli indirizzi di memoria.
Supponiamo di chiedere alla CPU di memorizzare una variabile contenente un numero molto grande, e di farne ricorso più volte durante il lo svolgimento del  programma. Costringiamo la CPU ad assegnare diverse aree di memoria per contenere lo stesso dato, con inutile spreco di risorse. Se invece creiamo una variabile che punti solo all’indirizzo di memoria, che contiene il dato che ci serve, questo eviterebbe alla CPU un inutile spreco di memoria.

Per rispondere alla domanda cosa è un puntatore: Un puntatore si comporta, in tutto e per tutto come una variabile e va dichiarato cosa dovrà contenere, ma esso non conterrà un valore in se ma un indirizzo di memoria che a sua volta conterrà il valore che ci serve.

Analizziamo l’immagine che segue:

puntatori2
Come si vede nell’immagine, il nostro puntatore, memorizzato all’indirizzo 0x192BA4, conterrà come valore l’indirizzo di memoria 0x192BA2.
A questo indirizzo di memoria troveremmo il valore 1211. In molti casi memorizzare una semplice indirizzo è molto più semplice e breve di memorizzare il valore a cui punta, che potrebbe essere molto grande.

Dichiariamo un puntatore

In C, come abbiamo capito, ogni variabile ha due tipologie di valori, un indirizzo di memoria e il valore in esso contenuto.
L’operatore & permette di ottenere l’indirizzo di memoria di una variabile.
L’operatore * (o detto anche star), ci consente di avere il contenuto dell’indirizzo di memoria.

Per dichiarare un puntatore la sintassi è la seguente:

int *puntatore; //è lo stesso scrivere: int* puntatore;

Come già spiegato, anche con i puntatori, come per le variabili, va sempre definito il tipo di dati che conterrà.

Ecco un esempio pratico:

int *puntatore; //definisco una variabile puntatore di nome puntatore
int a = 15;
int b = 0;

puntatore = &a; //in questo modo puntatore conterrà l'indirizzo di memoria di a
b = *puntatore; // b conterrà il valore di *puntatore, ovvero 15 

Ora analizzeremo un nuovo concetto.

Puntatori e Array

Un puntatore può puntare, oltre che ad una comune variabile, anche ad un array, da vedersi come un insieme di locazioni di memoria consecutive.

puntatori-array

Se ad esempio definiamo l’array a[] in questo modo:

int a[4] = {3, 12, 6, 5};

E supponiamo che l’indirizzo di memoria da cui parte a[] sia 0x0AFC.
Definaiamo un puntatore che punta a questo indirizzo:

int *p1;
p1 = &a[0];

In questo modo, il puntatore p1, conterrà l’indirizzo di memoria 0x0AFC da cui parte l’array a[0].

Se vogliamo leggere, tramite puntatore, il contenuto dell’array a[2] (che contiene, nel nostro caso, il valore 6) dovremo fare così:

//definiamo il nostro array, puntatore e variabile
int a[4] = {3, 12, 6, 5};
int *p1;
int f = 0;

//leggiamo il contenuto dell'array, tramite puntatore, utilizzando l'indirizzo di memoria di a[2] che sarebbe 0x0AFE
p1 = &a[2]; //0x0AFE
f = *p1; // 6

Proviamo ad inserire l’esempio nel nostro compilatore online:

compilatore-puntatori

Fate delle prove voi stessi, vi aspetto al prossimo articolo Smile-Ammicca

Se ti è piaciuto l'articolo e apprezzi il mio lavoro potresti aiutarmi con una piccola donazione, tramite PayPal, offrendomi un cappuccino.
Grazie di cuore!
Dona