I puntatori in C sono fondamentali per generare del codice efficiente.
I puntatori sono fondamentalmente delle variabili che rappresentano la locazione di altri elementi nel programma, come variabili, strutture, funzioni, array, file, ecc…
Abbiamo già parlato delle variabili in questo articolo: variabili.
Adesso precisiamo che ad ogni variabile corrisponde un nome, una locazione di memoria e l’indirizzo della locazione di memoria.
Infatti le variabili sono memorizzate nella memoria RAM del computer in un indirizzo specifico e per un numero di byte corrispondente alla loro dimensione.
Quindi in C l’operatore &, che abbiamo utilizzato nella funzione scanf, ci restituisce l’indirizzo di memoria di una variabile.
Dobbiamo precisare che l’indirizzo restituito non è quello fisico ma quello logico precedente la traslazione da parte della MMU del processore che appunto gestisce le richieste di accesso alla memoria.
Un indirizzo può essere assegnato solo a una speciale categoria di variabili denominate puntatori.
Quindi i puntatori sono variabili abilitate a contenere un indirizzo.
Innanzitutto diciamo che, una variabile di tipo puntatore viene dichiarata premettendo il simbolo * (operatore unario) al nome della variabile. L’operatore * viene anche denominato operatore di in-direzione.
Dunque questa è la sintassi della dichiarazione dei puntatori in C:
tipo *nome_var;
Quindi facciamo alcuni esempi di dichiarazione delle variabili puntatore:
int *pa; // puntatore ad una variabile intera
char *pc; //puntatore ad una variabile char
float *pf; //puntatore ad una variabile float
void *p; //puntatore a void
Appena dichiarati i puntatori sono inizializzati al valore speciale NULL.
Esempio di utilizzo dei puntatori in C
Iniziamo facendo dei semplicissimi esempi sulla dichiarazione di un puntatore in C.
int *pa, a; //pa è una variabile di tipo puntatore ad int
pa=&a //il puntatore pa assume l’indirizzo di a
Quindi provate ad eseguire questo semplice codice, vedrete che stamperà l’indirizzo della variabile a.
int main(void) {
int *pa, a=10;
pa=&a;
printf("Indirizzo della variabile: %x ", pa);
printf("Valore variabile: %d ", *pa);
//oppure avrei potuto scrivere: printf("Valore variabile: %d ", a);
return 0;
}
N.B. Al posto di %x si può utilizzare %p, anche perchè talvolta (raramente) %x può generare un comportamento errato quando si porta un programma nelle architetture a 64 bit.
Dopo aver assegnato a pa l’indirizzo di a, è possibile accedere alla stessa area di memoria in due modi diversi:
attraverso la variabile a;
attraverso la dereferenziazione di pa, cioè *pa.
Facciamo ancora un semplice esempio:
int *pa, a;
pa=&a;
*pa=10; // è equivalente a scrivere a=10
Infatti, se compilate questo codice, verrà stampato il valore 10 perché il puntatore pa assume l’indirizzo di a (pa=&a).
int main(void) {
int *pa, a;
pa=&a;
*pa=10; // è equivalente ad a=10
printf("Il valore di a e': %d ", a);
return 0;
}
Secondo esempio
Per capire meglio il concetto di variabile puntatore, modifichiamo l’esempio di prima:
int *pa, *pb, a;
pa=&a;
pb=pa;
*pb=10;
Abbiamo assegnato alla seconda variabile puntatore pb il contenuto di pa e quindi l’indirizzo di memoria della variabile a.
In questo caso *pb=10 è equivalente a scrivere *pa=10 e a=10;
Infatti provate a compilare il codice sotto, stamperà che la variabile a vale 10.
int main(void) {
int *pa, *pb, a;
pa=&a;
pb=pa;
*pb=10;
printf("Il valore di a e': %d ", a);
return 0;
}
Nell’esempio sopra abbiamo assegnato ad un puntatore un altro puntatore (pb=pa) ma attenzione devono essere compatibili, cioè devono riferirsi allo stesso tipo di dati per avere il risultato desiderato. Se vogliamo trasformare un puntatore in modo che si riferisca ad un tipo di dati differente allora dovremmo utilizzare il cast.
Assegnazioni tra puntatori in C
Facciamo quindi un esempio:
char *pc;
int *pa;
pa=(int *) pc; //in questo caso dunque il cast rende possibile l’assegnazione tra puntatori
Alcuni link utili
Realizzare un menù di scelta in C
Somma elementi diagonale principale di una matrice
Come sommare gli elementi della cornice esterna
Sommare dei numeri di una matrice
Ricerca elementi in una matrice