【问题标题】:function as parameter vs function pointer as parameter函数作为参数与函数指针作为参数
【发布时间】:2012-02-26 17:20:22
【问题描述】:

在听斯坦福的Programming Abstractions 课程时,我遇到了一些如下所示的代码。

void plot(double start, double end, double (fn)(double)) {
    double i;
    for (i = start; i <= end; i += 1)
        printf("fn(%f) = %f\n", i, fn(i));
}

double plus1(double x) {
    return x + 1;
}

int main(void) {
    plot(1, 10, plus1);
    return 0;
}

我在我的系统上使用 GCC 编译了代码,然后是 G++;它们都运行良好。

我知道将int i = 2 传递给诸如void func1(int a) 之类的函数将为该函数创建i 的新副本,而将&amp;i 传递给void func2(int *a) 只会给函数func2 i的地址。

那么任何人都可以向我解释将fn 传递给plot 的机制是什么以及它与将函数指针作为参数传递有何不同?

【问题讨论】:

    标签: c++ c function parameters


    【解决方案1】:

    void foo(double fn(double))void foo(double (*fn)(double)) 之间绝对没有区别。两者都声明了将指向函数的指针作为参数的函数。

    这类似于void bar(double arr[10])void bar(double* arr) 之间没有区别。

    【讨论】:

    • 您有关于数组的第二个声明的参考吗?尤其是当它是 C++ 的时候?
    • 有点区别,前者fn是隐含的函数指针,而后者fn是显式声明的函数指针
    • @user946850: §8.3.5/5: ...确定每个参数的类型后,将“T的数组”或“返回T的函数”类型的任何参数调整为“指向T的指针”或“指向返回 T 的函数的指针”。 ...
    • @Mr.Anubis:你可以选择这样想,但是没有办法检测到差异,所以我看不出它是什么相关点。
    • 您可以很容易地看到编译器将 a[x] 评估为 *(a + x)。如果你写 char *s = "Hello"; 并使用 s[3]3[s] 它将完全一样。
    【解决方案2】:

    抱歉我的错误。

    void foo(int (fn)(int)){}
    void bar(int (*fn)(int)){}
    

    像这样编译上面的代码:

    gcc -S 样本.c

    你会发现没有什么不同。 只是编码风格不同。

    您也可以尝试编译并运行此代码:

    #include <stdio.h>
    void foo(int (fn)(int))
    {
        printf("foo: %x.\n",fn);
    }
    void bar(int (*fn)(int))
    {
        printf("bar: %x.\n",fn);
    }
    int main(int argc)
    {
        foo(main);
        bar(main);
        return 0;
    }
    

    【讨论】:

    • 请再次阅读我的问题。我询问了参数列表中的函数指针与参数列表中的函数原型之间的区别。
    • 我的错。我写了一个新答案。