如何在C中将函数作为参数传递?

时间:2008-08-13 02:16:33

标签: c function pointers syntax parameters

我想创建一个函数来执行一组数据上由参数传递的函数。如何将函数作为参数传递给C?

8 个答案:

答案 0 :(得分:668)

<强>声明

带有函数参数的函数原型如下所示:

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

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

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

功能调用

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

func(print);

会调用func,将打印功能传递给它。

功能正文

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

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

由于func的参数声明表明f是指向所需函数的指针的名称,我们首先回想一下,如果f是一个指针,那么*ff指向的东西(即本例中的函数print)。因此,只需使用*f

替换上面循环中每次出现的print
void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

来自http://math.hws.edu/bridgeman/courses/331/f05/handouts/c-c++-notes.html

答案 1 :(得分:119)

这个问题已经有了定义函数指针的答案,但是它们会变得非常混乱,特别是如果你要在应用程序中传递它们。为了避免这种不愉快,我建议你将函数指针键入为更可读的东西。例如。

typedef void (*functiontype)();

声明一个返回void并且不带参数的函数。要创建一个指向此类型的函数指针,您现在可以执行以下操作:

void dosomething() { }

functiontype func = &dosomething;
func();

对于返回int并接受char的函数,您将执行

typedef int (*functiontype2)(char);

并使用它

int dosomethingwithchar(char a) { return 1; }

functiontype2 func2 = &dosomethingwithchar
int result = func2('a');

有些库可以帮助将函数指针转换为可读的类型。 boost function库很棒,值得付出努力!

boost::function<int (char a)> functiontype2;

比上面的好得多。

答案 2 :(得分:58)

从C ++ 11开始,您可以使用functional library以简洁和通用的方式执行此操作。语法是,例如,

std::function<bool (int)>

其中bool是一个单参数函数的返回类型,其第一个参数的类型为int

我在下面列出了一个示例程序:

// g++ test.cpp --std=c++11
#include <functional>

double Combiner(double a, double b, std::function<double (double,double)> func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

但有时候,使用模板功能会更方便:

// g++ test.cpp --std=c++11

template<class T>
double Combiner(double a, double b, T func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

答案 3 :(得分:14)

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

#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();
}

答案 4 :(得分:4)

您需要传递function pointer。语法有点麻烦,但是一旦你熟悉它就会非常强大。

答案 5 :(得分:2)

我将用一个简单的示例代码来解释,该代码将一个 compare 函数作为另一个 sorting 函数的参数。 假设我有一个冒泡排序函数,它采用自定义比较函数并使用它而不是固定的 if 语句。

比较函数

bool compare(int a, int b) {
    return a > b;
}

现在,冒泡排序以另一个函数为参数进行比较

冒泡排序功能

void bubble_sort(int arr[], int n, bool (&cmp)(int a, int b)) {

    for (int i = 0;i < n - 1;i++) {
        for (int j = 0;j < (n - 1 - i);j++) {
            
            if (cmp(arr[j], arr[j + 1])) {
                swap(arr[j], arr[j + 1]);
            }
        }
    }
}

最后,main 通过将布尔比较函数作为参数传递来调用冒泡排序函数。

int main()
{
    int i, n = 10, key = 11;
    int arr[10] = { 20, 22, 18, 8, 12, 3, 6, 12, 11, 15 };

    bubble_sort(arr, n, compare);
    cout<<"Sorted Order"<<endl;
    for (int i = 0;i < n;i++) {
        cout << arr[i] << " ";
    }
}

输出:

Sorted Order
3 6 8 11 12 12 15 18 20 22

答案 6 :(得分:1)

它实际上不是一个函数,但它是一段本地化的代码。当然,它不会仅将结果传递给代码。如果传递给事件分派器以在以后运行(因为结果是现在计算的,而不是事件发生时才计算的),则它将不起作用。但是,如果您要这样做,它将把代码本地化到一个地方。

#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;
}

答案 7 :(得分:1)

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

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

等效于此:

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