使用函数或指向函数的指针之间有什么区别吗?

Is there any distinction between using function or pointer to function notation?

考虑以下程序:

#include <stdio.h>

void f() {}
void g1(void fun(void)) { printf("%p\n", &fun); }
void g2(void (*fun)(void)) { printf("%p\n", fun); }

int main(void) {
    g1(f);
    g2(&f);
    printf("%p\n", &f);
    return 0;
}

由于 C11 没有 lambda 表达式,所以无法将文字函数作为参数传递给 g1g2,所以在某种程度上,这两个函数做同样的事情(必须先定义参数);我现在正在读一本书

The fact that technically this function (f) is passed on as a function pointer (to g1) is usually of minor interest, [...]

所以,我的理解是作者是说两者在语义上是等价的。

但是调用g1g2打印出来的地址是不一样的,g2输出的是f的真实地址。这意味着 g1 复制了 f,这意味着 f 是按值传递的。是书错了还是我错了?我不认为这本书有错,但地址不同,当然你选择哪一个很重要。如果有什么区别,在什么情况下应该优先选择哪一个?

你大错特错了

当您认为将函数传递给函数时,实际上是在传递指向它的指针。
每当一个函数看起来有一个函数参数时,它实际上有一个函数指针参数。

现在,在您的一个函数中打印指向参数的指针的值,在另一个函数中打印参数。除了 %p 适用于 void* 而不是其他数据指针,尤其是函数指针,这意味着你有未定义的行为,有充分的理由期望它们有所不同,尤其是在具有用于数据和指令的共享地址 space 的体系结构上。

But the addresses that get printed when calling g1 and g2 are different, where g2 outputs the real address of f. This means that g1 makes a copy of f, meaning that f is passed by value.

你错了。在g1g2中,变量fun都是函数指针,不是函数。在 g1 中使用 &fun 给出存储函数指针的地址(在堆栈上)——而不是函数的实际地址。

函数不是 C 或 C++ 中的值。它们不能被复制,也不能按值传递。