Puntatore (programmazione)

Da Wikipedia, l'enciclopedia libera.

In programmazione, i puntatori sono tipi di dati che rappresentano la posizione (usando indirizzi di memoria) di elementi del programma come variabili, oggetti, strutture di dati, sottoprogrammi.

In generale, i puntatori consentono l'indirizzamento indiretto nei linguaggi di programmazione ad alto livello; fra le applicazioni specifiche vi sono la creazione di strutture dati dinamiche e la simulazione del passaggio di parametri per riferimento in funzioni nei linguaggi che consentono solo il passaggio di parametri per valore.

Un concetto strettamente legato ai puntatori è quello di riferimento o reference.

Tipi di puntatore[modifica | modifica sorgente]

Nei linguaggi tipizzati, ogni puntatore ha un tipo ben definito, derivato dal tipo dell'oggetto puntato. Così, l'indirizzo di memoria di una variabile di tipo "numero intero" si dirà essere di tipo "puntatore a numero intero", e questo sarà considerato dal linguaggio come un tipo distinto da "puntatore a carattere" o altri tipi puntatore. Il tipo dell'oggetto puntato viene spesso detto tipo base del puntatore (con terminologia analoga a quella usata per gli array). I tipi puntatori possono essere impiegati anche nella dichiarazione di variabili (o in altri contesti analoghi). Per esempio, nel linguaggio C

 int n;
 char c;

dichiara n come variabile di tipo int (numero intero) e c come char (carattere);

 int* pn;
 char* pc;

dichiara pn come "puntatore a intero" e pc come "puntatore a carattere". Questi due tipi sono considerati dal linguaggio come distinti e (almeno in linea di principio), incompatibili; un assegnamento come

 pc = pn;

verrà segnalato dal compilatore come errore.

Operazioni sui puntatori[modifica | modifica sorgente]

Un esempio grafico delle operazioni di assegnamento di un puntatore

L'operazione fondamentale che si può eseguire su un valore di tipo puntatore viene detta dereferenziazione (dereferencing) oppure operazione di risoluzione del riferimento; è rappresentata da un operatore unario che, applicato a un puntatore, produce come risultato l'oggetto puntato. Così, con riferimento all'esempio della sezione precedente,

 *pn = 3;

("*" è il simbolo dell'operatore di dereferenziazione), assegna "3" alla variabile intera puntata da pn.

Un'altra operazione piuttosto comune relativa ai puntatori (non fornita da tutti i linguaggi) consente di ottenere un puntatore a una data variabile, ovvero calcolarne l'indirizzo; l'operatore corrispondente (anch'esso unario) viene spesso detto "operatore indirizzo-di". In C e in C++ questo operatore è rappresentato dal simbolo "&":

 pn = &n;

assegna al puntatore pn l'indirizzo della variabile n. Finché pn manterrà tale valore, qualsiasi uso del puntatore derefenziato, come

 *pn = 4;

avrà effetto sulla variabile n puntata da pn.

Alcuni linguaggi (in particolare della famiglia del C) forniscono un insieme supplementare di operazioni sui valori di tipo puntatore, pensati soprattutto per la navigazione all'interno di array; essi vanno sotto il nome di aritmetica dei puntatori.

I puntatori possono essere usati anche per chiamare funzioni, in tal caso si parla di puntatori a funzione. Supponiamo di avere 2 funzioni:

 int f1(double);
 int f2(double);

allora è possibile creare un puntatore a funzione in questa maniera:

 int (*pfunz)(double);

A questo punto, si può decidere di far puntare il puntatore pfunz o alla prima funzione f1, o alla seconda funzione f2:

 if (condizione)
     pfunz = f1;
 else
     pfunz = f2;

Per invocare la funzione, basta dereferenziare il puntatore:

 int ris = pfunz(4.2);

Tutto questo meccanismo è valido solo se le funzioni hanno lo stesso tipo di ritorno e lo stesso numero di parametri dello stesso tipo.

Applicazioni[modifica | modifica sorgente]

L'uso di puntatori è spesso necessario per costruire strutture dati dinamiche (dalla forma non prevedibile a priori e/o variabile nel tempo) come grafi, alberi, liste e così via.

Un'altra applicazione classica dei puntatori consiste nel simulare il passaggio di parametri per riferimento in quei linguaggi che dispongono solo di passaggio di parametri per valore.

Il puntatore null[modifica | modifica sorgente]

Ogni linguaggio fornisce un valore speciale che può essere assegnato a una variabile di tipo puntatore per indicare che essa non punta a nessun oggetto. Questo valore viene generalmente detto NULL (NULL), e spesso corrisponde al valore "0" (che di norma non rappresenta un indirizzo di memoria valido).

Puntatori non validi[modifica | modifica sorgente]

Per "puntatore non valido" si intende in genere una variabile di tipo puntatore non inizializzata, ovvero alla quale non è mai stato assegnato l'indirizzo di alcun oggetto. A seconda dei linguaggi e dei contesti, questo può comportare che la variabile contenga un valore "casuale" oppure il valore null.

La dereferenziazione di un puntatore "non valido" spesso genera un errore di sistema o un'eccezione. Nel caso peggiore (quello in cui il puntatore contiene un valore "casuale" che però, fortuitamente, corrisponde a una locazione di memoria), essa potrebbe portare a una violazione grave della coerenza interna della memoria del programma, con risultati imprevedibili e non raramente disastrosi. Per questo motivo l'uso scorretto di puntatori può portare a malfunzionamenti le cui cause sono molto difficili da individuare e correggere. Alcuni linguaggi tentano di limitare l'uso dei puntatori o addirittura di eliminarli completamente (un esempio in questo senso è Java); all'eliminazione dei puntatori deve corrispondere in genere l'introduzione di altri meccanismi che consentano di ottenere risultati analoghi a quelli per i quali si usano solitamente i puntatori (le limitazioni imposte da Java all'uso dei puntatori, per esempio, sono controbilanciate dal suo meccanismo di garbage collection).

Meccanismi correlati[modifica | modifica sorgente]

  • Il linguaggio C++ fornisce due costruttori di tipo correlati; il puntatore in senso stretto e il riferimento, un tipo speciale di puntatore a dereferenziazione implicita.
  • Java fornisce un concetto analogo a quello di puntatore (anch'esso detto riferimento), con funzionalità limitate.