Puntatore (programmazione)

Rappresentazione di un puntatore nella memoria RAM

In programmazione, il puntatore è un tipo di dato che rappresenta l'indirizzo di memoria che contiene una data variabile, o in generale un oggetto oppure una struttura dati.

Tipi di puntatore

[modifica | modifica wikitesto]

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, dato che nella pratica entrambi contengono un valore numerico indicante l'indice dello slot di memoria puntato) incompatibili; un assegnamento come

 pc = pn; 

verrà segnalato dal compilatore come errore.

Puntatore null

[modifica | modifica wikitesto]

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 wikitesto]

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).

Operazioni sui puntatori

[modifica | modifica wikitesto]
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 dereferenziato, 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.

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.

Voci correlate

[modifica | modifica wikitesto]

Altri progetti

[modifica | modifica wikitesto]

Collegamenti esterni

[modifica | modifica wikitesto]
Controllo di autoritàGND (DE4285887-2
  Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica