考虑以下程序:
#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表达式,因此无法将文字函数作为参数传递给g1
或g2
,因此,从某种意义上讲,这两个函数具有相同的作用(您必须先定义参数);我正在读一本书,上面写着
从技术上讲,此函数(
f
)作为函数传递 指向g1
的指针通常没有什么用,[...]
所以,我的理解是作者说这两个词在语义上是等效的。
但是调用g1
和g2
时打印的地址不同,其中g2
输出f
的实际地址。这意味着g1
复制了f
,这意味着f
是按值传递的。这本书是错的还是我?我认为这本书没有错,但是地址不同,当然,选择哪一个很重要。而且,如果有任何区别,在哪种情况下应首选哪一个?
答案 0 :(得分:3)
你错了。
每当您认为将一个函数传递给一个函数时,实际上就是在将指针传递给该函数。
每当函数看起来像具有函数参数时,实际上就具有函数指针参数。
现在,在您的一个函数中,您将打印指向该参数的指针的值,在另一个函数中,您将打印该参数的指针。除了%p
不适合void*
而不适用于其他数据指针,尤其不适合函数指针这一事实之外,这意味着您具有未定义的行为,我们有充分的理由期望它们会有所不同,尤其是在具有用于数据和指令的共享地址空间的体系结构上。
答案 1 :(得分:3)
但是调用
g1
和g2
时打印的地址不同,其中g2
输出f
的实际地址。这意味着g1
复制了f
,这意味着f
是按值传递的。
您不正确。在g1
和g2
中,变量fun
是一个函数指针,而不是一个函数。在&fun
中使用g1
会给出函数指针存储的地址(在堆栈上),而不是函数的实际地址。
函数不是C或C ++中的值。它们不能被复制,也不能按值传递。