How do you pass a function as a parameter in C?
我想创建一个函数,它对一组数据执行参数传递的函数。如何在C中传递函数作为参数?
宣言
采用函数参数的函数的原型如下所示:
1 | void func ( void (*f)(int) ); |
这说明参数
1 2 3 4 |
函数调用
调用带有函数参数的函数时,传递的值必须是指向函数的指针。为此,请使用函数名(不带括号):
1 | func(print); |
调用
功能体
与任何参数一样,func现在可以在函数体中使用参数的名称来访问参数的值。假设func将应用传递给数字0-4的函数。首先,考虑直接调用print的循环是什么样子的:
1 2 3 | for ( int ctr = 0 ; ctr < 5 ; ctr++ ) { print(ctr); } |
由于
1 2 3 4 5 | void func ( void (*f)(int) ) { for ( int ctr = 0 ; ctr < 5 ; ctr++ ) { (*f)(ctr); } } |
摘自http://math.hws.edu/bridgeman/courses/331/f05/paddles/c-c++-notes.html
这个问题已经有了定义函数指针的答案,但是它们可能会变得非常混乱,特别是当您要在应用程序中传递它们时。为了避免这种不愉快,我建议您将函数指针类型化为更可读的类型。例如。
1 | typedef void (*functiontype)(); |
声明一个返回void且不接受参数的函数。要创建指向此类型的函数指针,现在可以执行以下操作:
1 2 3 4 | void dosomething() { } functiontype func = &dosomething; func(); |
对于返回int并接受char的函数
1 | typedef int (*functiontype2)(char); |
并使用它
1 2 3 4 | int dosomethingwithchar(char a) { return 1; } functiontype2 func2 = &dosomethingwithchar int result = func2('a'); |
有一些库可以帮助将函数指针转换为可读性好的类型。Boost函数库很棒,值得您付出努力!
1 | boost::function<int (char a)> functiontype2; |
比上面好多了。
由于C++ 11,您可以使用函数库以简洁和通用的方式来实现这一点。语法是,例如,
1 | std::function<bool (int)> |
其中
我在下面提供了一个示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // 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); } |
但是,有时使用模板函数更方便:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // 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); } |
将函数的地址作为参数传递给另一个函数,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #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(); } |
我们还可以使用函数指针传递函数作为参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #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(); } |
您需要传递一个函数指针。语法有点繁琐,但一旦熟悉它,它就非常强大。
它实际上不是一个函数,但它是一段本地化的代码。当然,它不会只传递结果。如果传递给事件调度器以便稍后运行(因为结果是现在计算的,而不是在事件发生时计算的),它将不起作用。但是,如果您只想将代码本地化到一个地方,那么它确实会将代码本地化到一个地方。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #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 ", a, b, IncMultInt(a, b)); b = 9; // Create some local code with it's own local variable printf("%d * %d = %d ", a, b, ( { int _a = a+1; _a * b; } ) ); return 0; } |
函数可以作为函数指针"传递",如6.7.6.3p8所示:"参数声明为"函数返回类型"应调整为"指向函数返回类型的指针",如6.3.2.1所示。"。例如:
1 | void foo(int bar(int, int)); |
相当于:
1 | void foo(int (*bar)(int, int)); |