un semplice esempio è un array di stringhe:

codice:
char* array_stringhe[];
Quello è un puntatore a puntatore, ovvero un array che punta al primo elemento, in questo il primo elemento è un puntatore a char che punta al primo carattere della stringa.

Altra utilità è per passare a riferimento un puntatore, ovvero se vuoi modificare il puntatore vero è proprio a non la cella di memoria a cui punta.

Praticamente un puntatore a puntatore fa questo:

codice:
-----------|         -----------        -----------
| int** ptr| ----->  | int* ptr2| ----> |   int   |
|----------|         ------------       -----------
ptr2 contiene l'indirizzo di memoria di int, e ptr quello di ptr2.
In questo modo puoi passare a riferimento la cella di memoria di ptr2.

Se non ricordo male il massimo è puntatore a puntatore a puntatore

codice:
int*** ptr_ptr_ptr;