使用函数或函数指针符号表示法有什么区别吗?

3

请考虑以下程序:

#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是按值传递的。是书错了还是我错了?我认为书没有错,但是地址不同,选择哪一个肯定很重要。如果有区别,那么在什么情况下应该使用哪一个?

3
知道就好,我用了-Wall -Wextra -std=c11 -pedantic编译了这个程序,得到了三个警告。 - klutt
1
是的,所有格式不匹配警告:http://coliru.stacked-crooked.com/a/a80c6b7a990222d9 - Deduplicator
2个回答

3

你非常错误。

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

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


你的意思是没有共享地址空间吗? - Jonathon Reinhart
@JonathonReinhart:如果您有一个共享地址空间,那么拥有可修改的堆栈和静态指令重叠会有一定难度。如果您没有共享地址空间,则数据:指针和代码:指针(其中指针相同)将是独立的。 - Deduplicator

3
但是,调用 g1g2 时打印的地址是不同的,其中 g2 输出了 f 的真实地址。这意味着 g1 复制了 f,也就是说 f 是按值传递的。
你的观点是错误的。在 g1g2 中,变量 fun 都是函数指针,而不是函数。在 g1 中使用 &fun 给出了存储函数指针的地址(在栈上),而不是函数的实际地址。
在 C 或 C++ 中,函数不是值。它们不能被复制,也不能按值传递。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接