Advanced Pointers
You thought pointers were hard? Wrong. The rest is just applying the same one idea, "a variable holding an address", one more layer deep.
Pointers to pointers
A pointer can point at another pointer, useful whenever a function needs to modify which address the caller's pointer holds, not just the value at that address:
int **outPtr reads right-to-left: "outPtr is a pointer to (a pointer to an int)". *outPtr gives you the inner pointer, **outPtr dereferences all the way down to the int itself.
Pointers and arrays
An array name, used in most expressions, "decays" into a pointer to its first element, this is why array indexing and pointer arithmetic are interchangeable in C:
p + 1 doesn't add 1 byte, it adds 1 * sizeof(int) bytes, pointer arithmetic automatically scales by the size of whatever type the pointer points to.
Function pointers
A pointer can even point at executable code, letting you pass a function around like a value:
int (*fn)(int) declares fn as "a pointer to a function taking an int and returning an int", this is the mechanism behind callbacks in C, and it's exactly how the object system you'll build next represents dynamic behavior.
NOTE
The in-browser interpreter running these examples doesn't support function pointer syntax, so clicking Run on the snippet above will show a parse error instead of 25. The code itself is valid, standard C, you'd see it work correctly with a real compiler like gcc, this is a limitation of the lightweight interpreter, not a mistake in the example.