【问题标题】:Is there any distinction between using function or pointer to function notation?使用函数或指向函数符号的指针之间有什么区别吗?
【发布时间】:2018-07-16 22:51:52
【问题描述】:

考虑以下程序:

#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,所以在某种程度上,这两个函数做同样的事情(你必须定义参数第一的);我现在正在读一本这样说的书

从技术上讲,这个函数 (f) 是作为函数传递的事实 指针(指向g1)通常是次要的,[...]

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

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

【问题讨论】:

标签: c function-pointers c11 function-prototypes function-parameter


【解决方案1】:

你错了。

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

现在,在您的一个函数中,您在另一个函数中打印指向参数的指针的值。除了%p 用于void* 而不是其他数据指针,尤其不是函数指针,这意味着您有未定义的行为之外,完全有理由期望它们有所不同,尤其是在具有数据和指令的共享地址空间。

【讨论】:

  • 您的意思是没有共享地址空间吗?
  • @JonathonReinhart:如果您有一个共享地址空间,那么让可修改堆栈和静态指令重叠有点困难。如果您没有一个共享地址空间,则 data:pointer 和 code:pointer(指针相同)将是独立的。
【解决方案2】:

但是调用g1g2时打印的地址是不同的,g2输出的是f的真实地址。这意味着g1 复制了f,这意味着f 是按值传递的。

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

函数不是 C 或 C++ 中的值。不能复制,不能传值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多