There're already a bunch of related questions such as
Function pointers and address of a function
and
Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?
But I'm curious about the reason of why it's like so, rather than simply memorizing all those rules.
Below is a trivial C code snippet and corresponding arm assembly code:
int foo() {
    return 42;
}
int main() {
    int (*bar)() = foo; // same assembly code if swapping with '&foo' 
    int a, *b;
    a = foo();
    *b = bar();
}
foo:
        str     fp, [sp, #-4]!
        add     fp, sp, #0
        mov     r3, #42
        mov     r0, r3
        add     sp, fp, #0
        ldr     fp, [sp], #4
        bx      lr
main:
        push    {fp, lr}
        add     fp, sp, #4
        sub     sp, sp, #16
        ldr     r3, .L5
        str     r3, [fp, #-8]
        bl      foo
        str     r0, [fp, #-12]
        ldr     r3, [fp, #-8]
        blx     r3
        mov     r2, r0
        ldr     r3, [fp, #-16]
        str     r2, [r3]
        mov     r3, #0
        mov     r0, r3
        sub     sp, fp, #4
        pop     {fp, pc}
.L5:
        .word   foo
As can be seen in ldr r3, .L5 the function name is presented as a label which is equivalent to address of code block, if I swap foo with &foo, the assembly code is still the same, because foo has no storage address. But pointer b and the value it points to have their dedicated storage. Therefore it's reasonable to not distinguish foo and &foo but necessary for b and *b. 
However, I can't find any solid reference to support my hypothesis; all the answers I've found are merely describing the phenomenon rather than explaining the reason?
 
    