L'indiretta multipla si verifica generalmente nei seguenti scenari: scrittura su un parametro del tipo di puntatore e creazione di un array N-dimensionale per pezzo.
Scrittura su un parametro del tipo di puntatore
Per qualsiasi parametro di funzione di tipo T
, se vuoi che la funzione modifichi il valore del parametro e abbia il nuovo valore riflesso nel chiamante, devi passare un puntatore:
void foo( T *ptr )
{
*ptr = new_value(); // writes new value to thing pointed to by ptr
}
void bar( void )
{
T var;
foo( &var ); // writes new value to var
}
L'espressione *ptr
in foo
fa riferimento allo stesso oggetto in memoria come var
in bar
, quindi scrivere a *ptr
equivale a scrivere a var
.
Se T
è un tipo di puntatore Q *
, si finisce con un puntatore a un puntatore:
void foo( Q **ptr )
{
*ptr = new_value(); // writes new value to thing pointed to by ptr
}
void bar( void )
{
Q *var;
foo( &var ); // writes new value to var
}
In questo secondo caso, si desidera modificare il valore del puntatore memorizzato in var
. Ancora una volta, sia *ptr
che var
si riferiscono alla stessa posizione di memoria, ma questa volta, var
contiene un valore puntatore. Puoi sostituire Q
con R *
, dando
void foo( R ***ptr )
{
*ptr = new_value(); // writes new value to thing pointed to by ptr
}
void bar( void )
{
R **var;
foo( &var ); // writes new value to var
}
La semantica è la stessa in tutti e tre i casi; scriviamo un nuovo valore in var
attraverso l'espressione *ptr
; è solo il tipo di var
è un tipo di puntatore, il che significa che il tipo di ptr
deve essere un tipo di puntatore con un ulteriore livello di riferimento indiretto.
Costruire un array N-dimensionale per pezzo
Supponiamo di voler allocare una matrice N
x M
di T
, ma non si conoscono i valori di N
o M
in fase di compilazione. Un approccio è quello di dichiarare un puntatore a un puntatore, quindi allocare una serie di puntatori ad esso:
T **arr; // arr will point to an NxM array of T
size_t n, m;
/**
* get values for n and m
*/
arr = malloc( sizeof *arr * n ); // allocate N objects of type T *
if ( arr )
{
for ( size_t i = 0; i < n; i++ )
{
arr[i] = malloc( sizeof *arr[i] * m ); // allocate M objects of type T
if ( arr[i] )
{
for ( size_t j = 0; i < m; i++ )
{
arr[i][j] = some_value();
}
}
}
}
Lo stesso meccanismo generale può essere applicato per matrici di dimensioni maggiori:
T ***arr3;
...
arr3 = malloc( sizeof *arr3 * n );
...
arr3[i] = malloc( sizeof *arr3[i] * m );
...
arr3[i][j] = malloc( sizeof *arr3[i][j] * k );
Ci sono alcuni altri scenari in cui vedi più riferimenti indiretti, ma quelli sono i due principali.
In pratica è raro vedere più di tre livelli di riferimento indiretto, però.