- Programmazione » Programmazione » Guida C - Manuale programmazione con articoli e risorse interessanti
L'aritmetica dei puntatori
PUNTATORI
Quanti byte di memoria occupa un array? La risposta dipende,
ovviamente, dal numero degli elementi e dal tipo di dato
dichiarato. Un array di 20 interi occupa 40 byte, dal momento
che ogni int ne occupa 2. Un array di 20
long ne occupa, dunque, 80. Calcoli analoghi
occorrono per accedere ad uno qualsiasi degli elementi di un
array: il terzo elemento di un array di long ha
indice 2 e dista 8 byte (2*4) dall'inizio dell'area
di RAM riservata all'array stesso. Il quarto elemento di
un array di int dista 3*2 = 6 byte dall'inizio
dell'array. Generalizzando, possiamo affermare che un
generico elemento di un array di un qualsiasi tipo dista
dall'indirizzo base dell'array stesso un numero di
byte pari al prodotto tra il proprio indice e la dimensione
del tipo di dato.
Fortunatamente il compilatore C consente di accedere agli
elementi di un array in funzione di un unico parametro: il
loro indice[20]. Per questo sono lecite e significative
istruzioni come quelle già viste:
iArr[1] = 12;
printf("%X
" ,iArr[j]);
E' il compilatore ad occuparsi di effettuare i calcoli
sopra descritti per ricavare il giusto offset in termini di
byte di ogni elemento, e lo fa in modo trasparente al
programmatore per qualsiasi tipo di dato.
Ciò vale anche per le stringhe (o array di
caratteri). Il fatto che ogni char occupi un byte
semplifica i calcoli ma non modifica i termini del
problema[21].
E' importante sottolineare che quanto affermato vale non
solo nei confronti degli array, bensì di qualsiasi
puntatore, come può chiarire l'esempio che
segue.
#include
int iArr[]= {12,99,27,0};
void main(void)
{
int *iPtr;
iPtr = iArr; // punta al primo elemento di iArr[]
while(*iPtr) { // finche' l'int puntato da iPtr non e' 0
printf("%X -> %d
" ,iPtr,*iPtr); // stampa iPtr e l'intero puntato
++iPtr; // incrementa iPtr
}
}
Il trucco sta tutto nell'espressione ++iPtr:
l'incremento del puntatore è automaticamente
effettuato dal compilatore sommando 2 al valore contenuto in
iPtr, proprio perché esso è un
puntatore ad int, e l'int occupa 2
byte. In altre parole, iPtr è incrementato,
ad ogni iterazione, in modo da puntare all'intero
successivo.
Si noti che l'aritmetica dei puntatori è
applicata dal compilatore ogni volta che una grandezza intera
è sommata a (o sottratta da) un puntatore,
moltiplicando tale grandezza per il numero di byte occupati
dal tipo di dato puntato.
Questo modo di gestire i puntatori ha due pregi: da un lato
evita al programmatore lo sforzo di pensare ai dati in
memoria in termini di numero di byte; dall'altro consente
la portabilità dei programmi che fanno uso di
puntatori anche su macchine che codificano gli stessi tipi di
dato con un diverso numero di bit.
Un'ultima precisazione: ai putatori possono essere
sommate o sottratte solo grandezze intere (int o
long, a seconda che si tratti di puntatori
near o no).