L'aritmetica dei puntatori

Come abbiamo detto, in un array gli elementi che lo compongono fanno riferimento ad aree di memoria contigue, dove ogni area di memoria è della grandezza del tipo dell'array.

Ad esempio, sappiamo che la definizione di un int richiede l'allocazione di 32 bit di memoria, e che ogni locazione di memoria RAM è formata da 8 bit, ed è contrassegnata da un indirizzo di memoria univoco.

Nella creazione di un array di int, sappiamo che ogni elemento è distante 32 bit dall'altro.
Sappiamo infine che il nome di un array è un puntatore alla locazione di memoria in cui inizia l'array. Perciò le due righe di codice seguenti sono equivalenti:

&nomeArray[0];
nomeArray;

Veniamo ora all'aritmetica dei puntatori:

int arrayInt[10]; //array di 10 elementi int
int *pInt; //puntatore a int

pInt = arrayInt; //ora pInt punta all'indirizzo dove inizia l'array

//vediamo ora l'indirizzo del primo elemento dell'array:

cout << &arrayInt[0];

//e l'indirizzo puntato da pInt, che ovviamente sarà lo stesso del precedente:

cout << pInt;

Nel mio caso stampa:

/> 0x7fff6c704b70 //&arrayInt[0];
/> 0x7fff6c704b70 //pInt;

Come possiamo vedere si tratta dello stesso indirizzo di memoria, com'era ovvio.
Proviamo ora a stampare l'indirizzo della locazione di partenza del secondo elemento dell'array:

cout << &arrayInt[1];

Che stampa:

/> 0x7fff6c704b74 //&arrayInt[1];

Come vedete la locazione di memoria del secondo elemento dell'array è 4 locazioni più avanti di quella del primo elemento. Questo perché, ormai lo saprete a memoria, ogni elemento è di tipo int, ed il tipo int richiede l'allocazione di uno spazio di 32 bit che equivale a 4 locazioni.

Ma cosa succede se faccio così?

pInt = pInt + 1; //sommiamo 1 al valore memorizzato in pInt e salviamo il risultato nello stesso pInt

Proviamo ora a stampare di nuovo pInt, e vediamo a che indirizzo di memoria punta, dopo avergli sommato + 1.
Basterà un cout, lo tralascio perché ormai sapete bene come si usa, mi limito a scrivere ciò che verrà stampato a schermo:

/> 0x7fff6c704b74

Prima dell'incremento a uno il puntatore puntava a 7fff6c704b70, mentre dopo l'incremento a uno, non punta alla locazione successiva (7fff6c704b71) come potremmo aspettarci, ma bensì a quattro locazioni più avanti, 7fff6c704b74, proprio lo stesso indirizzo del secondo elemento dell'array.
Come avrete intuito questo avviene proprio perché il + 1 non dice al puntatore di andare avanti di una locazione, ma di andare avanti di 32 bit * 1.
Se pInt fosse stato un puntatore a long, l'incremento a uno avrebbe portato ad uno spostamento di 8 locazioni, considerato che un long alloca un'area di memoria di 64 bit (8 byte, e cioé 8 locazioni).
Se facessimo:

pInt = pInt + 10;

Il puntatore punterebbe alla locazione di memoria che si trova a 32 bit * 10 da quella a cui punta attualmente.
Da questo è facile intuire che un puntatore può essere utilizzato per muoversi indirettamente tra gli elementi di un array.

Questo è tutto sull'aritmetica dei puntatori. Vi consiglio di sperimentare un po' anche con le sottrazioni, vi assicuro che è divertente e aiuta a familiarizzare con i puntatori.

Nessun commento:

Posta un commento