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?