I puntatori in C, cosa sono e come usarli in C

I puntatori rappresentano un concetto fondamentale della programmazione in C, nello specifico i puntatori sono delle variabili che contengono l’indirizzo di memoria di un’altra variabile. Questa caratteristica permette di agire direttamente sulla memoria fisica (indirizzi di memoria) e di generare del codice altamente efficiente.

Ogni qualvolta che vengono dichiarate delle variabili, esse saranno contenute in un certo luogo all’interno della memoria fisica. In particolare ad ogni variabile verrà assegnato un indirizzo di memoria con una certa dimensione che varia in base al tipo di dato assegnato alla variabile durante la sua dichiarazione. Risulta possibile visualizzare l’indirizzo di memoria di una variabile usando l'operatore &.

I puntatori sono delle variabili che possono immagazzinare queste specifiche posizioni all’interno della memoria fisica e si dirà che il puntatore punta ad una particolare variabile (o meglio al suo indirizzo di memoria).

Consideriamo il seguente esempio in cui vengono stampati a schermo gli indirizzi di memoria di alcune variabili, usando l’operatore &:



#include <stdio.h>

int main(){
    int x = 2;
    char c;
    char str[10];
    
    printf("Indirizzo di x: %x\n", &x);
    printf("Indirizzo di c: %x\n", &c);
    printf("Indirizzo di str: %x\n", &str);

    return 0;
}


Indirizzo di x: f898fb08 Indirizzo di c: f898fb07 Indirizzo di str: f898fb0e

Nota: la parte di memoria in cui vengono inserite, ad esempio, le variabili, prende il nome di heap e si tratta di una zona di memoria che man mano vengono aggiunti dati cresce verso il basso.

Il punto forte dei puntatori è il fatto che si possa manipolare, quindi modificare, la variabile puntata, inoltre il loro utilizzo risulta obbligatorio quando si ha che fare con l'allocazione dinamica di memoria.

Prima di poter utilizzare un puntatore, dobbiamo effettuare la sua dichiarazione, come con qualsiasi altra variabile, specificando il tipo di dato, l’asterisco (*) per specificare che si tratta di un puntatore, ed il nome da assegnare. Di seguito viene riportato la sintassi per dichiarare un puntatore in C:



tipo_dato *nome_variabile;

dove tipo_dato è un qualsiasi tipo di dato valido in C (int, float, …), mentre nome_variabile è il nome assegnato alla variabile puntatore. L’asterisco (*) serve per specificare che si tratta di un puntatore e deve essere posizionato prima del nome del puntatore (non per forza attaccato al nome). Consideriamo le seguenti dichiarazioni di variabili puntatori:



int *pi;
float *pf;
char *pc;


dove pi sarà un puntatore ad una variabile intera, pf ad una variabile float e pc ad una variabile char.

Nota: quando vengono dichiarati dei puntatori che non vengono utilizzati immediatamente, è buona programmazione assegnare il valore NULL (es. int *p = NULL;).

A questo punto possiamo usare i puntatori, per esempio per accedere al valore contenuto nella variabile puntata, attraverso la dereferenziazione del puntatore usando sempre l’operatore *.

Esempio di utilizzo di un puntatore in C

Consideriamo il seguente esempio in cui viene dichiarata una variabile intera, a cui assegniamo uno specifico valore, e un puntatore ad interi, a cui assegnamo l’indirizzo di memoria della variabile intera precedente:



#include <stdio.h>

int main(){
    int x = 56;
    int *p;
    
    p = &x;
    
    printf("Indirizzo variabile x: %x\n", &x);
    printf("Indirizzo variabile puntata da p: %x\n", p);
    printf("Valore della variabile puntata p: %d\n\n", *p);
    
    x = 2;
    
   printf("Nuovo valore della variabile puntata p: %d\n", *p);
    
   *p = 5;
    
   printf("Nuovo valore della variabile x (puntata da p): %d\n", x);

   return 0;
}


Indirizzo variabile x: eefe71cc Indirizzo variabile puntata da p: eefe71cc Valore della variabile puntata p: 56 Nuovo valore della variabile puntata p: 2 Nuovo valore della variabile x (puntata da p): 5

Possiamo notare che l’indirizzo puntato dalla variabile puntatore corrisponde all’indirizzo della variabile intera x, come anche il suo valore. Se andiamo a modificare il valore contenuto in x (esempio x=2) notiamo che anche il valore restituito dal puntatore è cambiato, questo perché la variabile p punta all’indirizzo di memoria di x. Allo stesso modo se viene dereferenziato il puntatore con *, possiamo assegnare un nuovo valore (esempio *p=5) alla variabile x, infatti le due scritture *p=5 e x=5, sono identiche.

Nota: anche quando utilizziamo un file in C, dobbiamo dichiarare una variabile puntatore di tipo FILE in modo da poter puntare all’indirizzo di memoria in cui è contenuta la posizione attuale di lettura o scrittura all’interno del file specificato.

Indice pagine linguaggio C: