a pointer to a pointer
If a pointer holds the address of a value, a pointer to a pointer holds the address of a pointer. The slip of paper now points at another slip of paper, which in turn points at the house. It sounds like one layer of indirection too many, but it shows up the moment a function needs to change which thing a caller's pointer points at.
Written with one extra star, a variable declared as a pointer to an int pointer holds the address of an int * variable. Following it works in steps: the first dereference gives you the inner pointer, and a second dereference gives you the int. The most common reason to want one is to let a function update a caller's pointer — for example a routine that allocates memory and writes the new pointer back into a pointer the caller owns, so it takes the address of that pointer. (The actual two-star declaration belongs in code, shown in the example.) Another everyday case is command-line arguments: main receives the address of an array of string pointers.
The honest caveat is that each layer is just another address to keep correct. A pointer to a pointer is not magic; it is the same '& to take an address, * to follow it' idea applied twice, and the same dangers apply twice. Most code never needs more than two levels, and going deeper is usually a sign that a small struct would read better.
void make(char out) { *out = some_buffer; } char *s; make(&s); — make receives the address of s (a char ), and *out = ... writes a new value into s itself. After the call, s points at some_buffer.
Pass &s (a pointer to a pointer) so the function can change s itself.
Two levels of indirection means two addresses that each must be valid before you follow them — dereferencing one star gives the inner pointer, which itself may be null or dangling. The parameter to main that lists program arguments is the textbook pointer to a char pointer; the example field shows its real two-star declaration form.