I was aware of implicit function pointer dereference rules in C. However, I somehow missed that explicit dereference is a bit magical as well.
Well, it turns out that a function pointer may be dereferenced to infinity and still remain itself, i.e. point to the same location. The example below illustrates this:
#include <stdio.h>
#include <stdint.h>
typedef int (* fn_ptr)(int);
int foo(int x)
{
return x + 42;
}
int main()
{
fn_ptr ptr = foo;
printf(" ptr: %lu\n", (uintptr_t)(ptr));
printf(" *ptr: %lu\n", (uintptr_t)(*ptr));
printf(" **ptr: %lu\n", (uintptr_t)(**ptr));
printf("********ptr: %lu\n", (uintptr_t)(********ptr));
return 0;
}
On my machine this gives the following output:
ptr: 4337163952
*ptr: 4337163952
**ptr: 4337163952
********ptr: 4337163952
A more detailed description is available in this SO thread: How does dereferencing of a function pointer happen?.