Programmare in C – I puntatori: concetti fondamentali

Guida completa al linguaggio C. I puntatori: concetti fondamentali. Per capire i puntatori, conviene confrontarli con le variabili “normali”.

Una variabile “normale” è la locazione di memoria che può contenere un valore. Per esempio, quando si dichiara la variabile i come un integer, quattro bytes di memoria vengono ad essa riservati. Nel programma, quindi, si farà riferimento a questo spazio di memoria con il nome di i. A livello macchina, questa locazione ha un indirizzo di memoria. I quattro bytes a quell'indirizzo sono noti a noi programmatori come i, e i quattro bytes possono contenere un valore intero.

Un puntatore è differente. Un puntatore è una variabile che punta ad un'altra variabile. Ciò significa che un puntatore mantiene in sé l'indirizzo di memoria di un'altra variabile. Detto in un altro modo, il puntatore non contiene un valore nel senso tradizionale, al contrario contiene l'indirizzo di un'altra varabile. Un puntatore “punta a” quest'altra variabile mantenendo al suo intero una copia del suo indirizzo.

Poiché un puntatore contiene un indirizzo di memoria piuttosto che un valore, è costituito da due parti. Il puntatore che contiene l'indirizzo e l'indirizzo che punta ad un valore. C'è quindi il puntatore e il valore a cui il puntatore punta. Questo aspetto può creare un po' di confusione finchè non si è raggiunto un certo grado di pratica, ma vi assicuriamo che questo concetto sarà fondamentale.

Il seguente codice descrive il tipico puntatore:

#include <stdio.h>

int main()
{
    int i,j;
    int *p;   /* a pointer to an integer */
    p = &i;
    *p=5;
    j=i;
    printf("%d %d %d\n", i, j, *p);
    return 0;
}

La prima dichiarazione in questo programma riguarda due variabili intere chiamate i e j. La linea int *p dichiara un puntatore chiamato p. Questa linea chiede al compilatore di dichiarare una variabile p che è il puntatore ad un interno. Il simbolo * indica che il puntatore viene dichiarato come tale piuttosto che come una variabile normale. Si possono creare puntatori a qualsiasi cosa: puntatori a float, a strutture, a caratteri e così via. Sarà sufficiente precedere la variabile con il simbolo * per dichiararla come puntatore.

La linea di codice p=&i descrive un nuovo concetto. Nel linguaggio C, il simbolo & è chiamato operatore indirizzo. L'espressione &i significa pertanto: “l'indirizzo di memoria della variabile i”. Quindi l'espressione p=&i significa assegna a p l'indirizzo di i. Una volta che questa istruzione viene eseguita, p punterà ad i. Prima di eseguire questa linea di codice, p contiene un indirizzo random sconosciuto. Se si userà p prima di “inizializzarlo” si potrebbe causare un crash del programma o in generale un errore di segmentatio fault.

Un modo semplice per rendersi conto di cosa succede è quello di simularlo tramite un disegno. Dopo che i, j e p sono state dichiarate, il ”mondo” del programma è questo:

dove nessuna delle tre variabili è stata inizializzata. I due interi sono in pratica due box che contengono punti interrogativi, poiché non è dato sapere a priori quali valori contengono (potrebbero contenere valori random). Il puntatore è disegnato come un cerchio per distinguerlo dalle variabili normali. Del puntatore non sappiamo a quale indirizzo di memoria punta, ecco spiegate le tre frecce. Il puntatore potrebbe contenere un indirizzo di memoria qualsiasi.

Dopo che la linea p=&i viene eseguita, il puntatore p viene inizializzato e punta ad i, come mostrato in figura:

poiché p ora punta ad i, la locazione di memoria i ha due nomi, il primo ovviamente è i, ma si può raggiungerla anche con *p. Questo è quello che il C chiama “le due parti di una variabile puntatore”. P è la locazione di memoria che contiene l'indirizzo, mentre *p è la locazione puntata da tale indirizzo. Per cui *p=5 significa che la locazione puntata da p deve essere impostata a 5, come in figura:

poiché la locazione *p è anche i, i conterrà il valore 5. Quindi eseguire j=i significa impostare j a 5 e quindi l'istruzione printf nel codice produrrà l'output 5 5 5.

Ecco quindi la principale caratteristica di un puntatore: la sua natura duale. Il puntatore stesso contiene un indirizzo. Il puntatore punta anche ad un valore specifico – il valore contenuto all'indirizzo. Ci si riferisce al puntatore stesso con p. Il valore a cui punta si esprime con *p.

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend