我想创建一个函数,它执行一组数据上通过参数传递的函数。如何在C中传递函数作为参数?


当前回答

宣言

接受函数形参的函数原型如下所示:

void func ( void (*f)(int) );

这说明形参f将是一个指针,指向一个具有void返回类型并接受单个int形参的函数。下面的函数(print)是一个可以作为参数传递给func的函数示例,因为它是正确的类型:

void print ( int x ) {
  printf("%d\n", x);
}

函数调用

当调用带有函数形参的函数时,传递的值必须是指向函数的指针。使用函数名(不带括号):

func(print);

调用func,将print函数传递给它。

函数体

与任何形参一样,func现在可以在函数体中使用形参的名称来访问形参的值。假设func将应用它传递给数字0-4的函数。首先,考虑直接调用print的循环会是什么样子:

for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
  print(ctr);
}

因为func的形参声明说f是指向目标函数的指针的名称,我们首先回想一下,如果f是一个指针,那么*f就是f指向的对象(即在这种情况下的函数打印)。因此,只需将上面循环中每次出现的print替换为*f:

void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

其他回答

你需要传递一个函数指针。语法有点麻烦,但是一旦你熟悉了它,它真的很强大。

将一个函数的地址作为参数传递给另一个函数,如下所示

#include <stdio.h>

void print();
void execute(void());

int main()
{
    execute(print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void f()) // receive address of print
{
    f();
}

也可以使用函数指针将函数作为参数传递

#include <stdio.h>

void print();
void execute(void (*f)());

int main()
{
    execute(&print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void (*f)()) // receive address of print
{
    f();
}

它不是一个真正的函数,但它是一段本地化的代码。当然,它不传递代码,只传递结果。如果将它传递给事件分派器以便稍后运行(因为结果是现在计算的,而不是事件发生时计算的),则它将不起作用。但是如果这就是你想要做的,它会把你的代码本地化到一个地方。

#include <stdio.h>

int IncMultInt(int a, int b)
{
    a++;
    return a * b;
}

int main(int argc, char *argv[])

{
    int a = 5;
    int b = 7;

    printf("%d * %d = %d\n", a, b, IncMultInt(a, b));

    b = 9;

    // Create some local code with it's own local variable
    printf("%d * %d = %d\n", a, b,  ( { int _a = a+1; _a * b; } ) );

    return 0;
}

函数可以作为函数指针“传递”,根据ISO C11 6.7.6.3p8:“将形参声明为“函数返回类型”应调整为“指向函数返回类型的指针”,如6.3.2.1。”。例如,这个:

void foo(int bar(int, int));

等价于:

void foo(int (*bar)(int, int));
typedef int function();

function *g(function *f)
{
    f();
    return f;
}

int main(void)
{
    function f;

    function *fn = g(f);

    fn();
}

int f() { return 0; }