A function (more precisely, a function designator) is converted to a pointer to a function (except when it is the operand of sizeof, _Alignof, or the unary &). So foo and &foo are the same thing because foo is automatically converted to &foo.
Similarly, p is a pointer to a function, so *p is the function, so it is automatically converted to the address of the function.
In fact, because *p is converted back to a pointer right away, you can apply * to it again, as in int b = (**p)();. And you can do that again and again and again: int b = (************p)();.
From the 2011 C standard (committee draft N1570), 6.3.2.1 4:
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”.
This is just a consequence of the fact that C developers wanted to make it easy to use both functions like foo and pointers-to-functions like p. If you had to write foo() for one and (*p)() for the other, that would be a bit of a nuisance. Or at least more typing. Or, if you had to write (&foo)() for one and p() for the other, that is again more typing. So they just said whenever you write a function, we will automatically make it the pointer, and you can call it without typing any more.
I suppose they could have said the function call operator can accept either a function or a pointer to a function, but they chose the automatic conversion instead.
Corollary: If you do not know whether something is a function, or a pointer to a function, or a pointer to a pointer to a function, etc., just slap a hundred asterisks in front of it, and the compiler will stop when it gets to the function.