C为什么函数指针作为参数而不仅仅是函数?

时间:2016-04-12 16:01:29

标签: c function pointers

我一直在阅读有关函数作为参数的函数,特别是在C中,它们使用函数指针。让我们假设我想实现牛顿拉夫森方法(用一种简单的方法)来计算非线性方程中的零点。

double derivative(double f(double), double x)
{
    double h = 1e-9;
    return (f(x + h) - f(x)) / h;
}

double newton_raphson(double f(double), double x0, double tol)
{
    double xk, diff;

    do
    {
        xk = x0 - f(x0) / derivative(f, x0);
        diff = fabs(xk - x0);
        x0 = xk;
    } while (diff >= tol);
    return xk;
}

因此,要计算导数的近似值,我需要一个返回double的函数,并将double作为参数。对于计算函数的根,给定其他参数也是如此。我的问题是,为什么这与将函数参数声明为函数指针不同?例如,将输入参数f声明为函数指针而不仅仅是函数...

2 个答案:

答案 0 :(得分:7)

参数fderivativenewton_raphson中指向函数的指针。

double derivative(double f(double), double x) { ... }

完全等同于

double derivative(double (*f)(double), double x) { ... }

只是,前者看起来更好 - 通常当你可以省略括号时,你应该这样做。毕竟它们都相当于

double ((((derivative)))(double (((*(f))))(double ((trouble))), double ((x)))) { ... }

我希望只会在IOCCC中使用。

但是,如果您要声明,定义变量(不是函数参数),则需要使用

double (*f)(double);

as

double f(double);

只是一个函数声明。

6.7.6.3 C11草案n1570的函数声明符(包括原型)说:

  

参数声明为''函数返回   类型   ''应调整为''指针   功能返回   类型   '',如6.3.2.1。

6.9.1函数定义进一步说明

  

[...]每个参数的类型按照6.7.6.3中的描述调整参数类型列表;结果类型应该是一个完整的对象   类型。

另外它有以下例子:

  

示例2

     

要将一个功能传递给另一个功能,可以说

int f(void);
/* ... */
g(f);
     

然后g的定义可能会读取

void g(int (*funcp)(void))
{
      /* ... *
      (*funcp)(); /* or funcp(); ... */
}
     

或等效

void g(int func(void))
{
      /* ... */
      func(); /* or (*func)(); ... */
}

答案 1 :(得分:0)

与普通数据指针一样,函数指针可以作为参数传递,也可以从函数返回。函数的名称包含函数的地址。

  

我的问题是,为什么这与将函数参数声明为函数指针不同?例如,将输入参数f声明为函数指针而不仅仅是函数...

答案是编译器将两种形式视为相同。 但是为了您的代码的可读性,请使用您的示例代码所具有的声明,即

double derivative(double f(double), double x) { ... }

即使在C中,下面给出的函数定义也将被解释为相同 -

void foo(int a[]) // or int a[10]
{
     ...
}

void foo(int *a)
{
     ...
}