【发布时间】:2020-02-27 06:45:31
【问题描述】:
已经有一堆相关问题如
Function pointers and address of a function
和
Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?
但我很好奇为什么会这样的原因,而不是简单地记住所有这些规则。
下面是一个简单的C代码sn-p和对应的arm汇编代码:
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
在ldr r3, .L5 中可以看到,函数名称显示为一个标签,相当于代码块的地址,如果我将foo 与&foo 交换,汇编代码仍然是相同的,因为@987654328 @ 没有存储地址。但是指针b 和它指向的值有它们的专用存储。因此,不区分foo 和&foo 是合理的,但对于b 和*b 是必要的。
但是,我找不到任何可靠的参考来支持我的假设;我找到的所有答案都只是描述现象而不是解释原因?
【问题讨论】:
-
除了直接调用函数之外,你可以在 C 中将函数作为对象做什么?
-
b和*b分别是int *和int;bar是指向函数的指针。但是bar是一个指针变量,就像b— 它有存储空间。相反,foo是地址常量,就像数组的名称是地址常量一样。它在被引用时衰减为指向函数的指针。没有必要记住太多的规则。重复引用或取消引用函数是愚蠢的(没有多个*或&)。我仍然喜欢(*pointer)(arg)表示我正在使用指向函数的指针,但pointer(arg)也可以正常工作。不需要在函数上使用&。 -
@JonathanLeffler 嗨 John 我刚刚在代码中添加了一条注释以使我的意图更加清晰,所以如果我将
foo与&foo交换,汇编代码仍然相同,因为 @987654349 @没有存储地址,不知道是不是foo等于&foo的原因? -
单个编译器从您的代码中创建什么并不重要。它们不一样,因为编译器不分配内存。情况恰恰相反。编译器不需要分配内存,因为 C 标准告诉我们它们是相同的。
-
像
foo这样的函数的名称映射到找到它的地址;&foo的唯一合理解释是它所在的地址。是的,它们是一样的。在函数调用符号(*pointer)(arg)之外(指针可以是函数名,但这很愚蠢),没有理由取消对函数指针的引用。基本上,你可以用函数做两件事;获取他们的地址并打电话给他们。
标签: c function-pointers