为啥将函数作为函数的参数传递?
Posted
技术标签:
【中文标题】为啥将函数作为函数的参数传递?【英文标题】:why pass as argument of a function a function?为什么将函数作为函数的参数传递? 【发布时间】:2019-07-10 17:27:25 【问题描述】:我有一个小问题。 我正在用 devc++ 学习 C(作为开始),我已经看到作为参数函数,你可以传递一个函数,这没关系,但为什么呢? 例如你可以写为参数:
void myfunc(void(*func)(int))
但是如果你用他的名字和参数简单地调用函数不是更好吗?
例如:
void myfunction ()name of func to call(myargs);
有区别吗? 看起来一样,但代码更简单更短
编辑:
我只想知道
void map (int (*fun) (int),int x[ ], int l)
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
为什么你用这个来代替:
void map (int x[ ], int l)
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
【问题讨论】:
你的意思是,例如,qsort() 需要一个函数作为参数?用户函数由qsort
调用,对数据项进行比较,否则对函数没有意义,只提供排序机制。
... 或者你的意思是,函数的唯一工作是调用另一个函数?这样做是为了可以将调用“修补”到另一个函数,或者在途中检查或修改其参数。例如,我可能打算写一个库函数的替代品,但现在我只调用原始函数。请提供一个示例,因为您的问题包含两种情况的示例。
因为:将函数作为参数传递可以让你用同一个数组做不同的事情。您可能有一个子函数递增int
,而另一个子函数递减int
。你有一个解析数组的函数,并且可以按照它被告知的方式修改每个元素。
nameofyourfunc(yourargs) type(*newnamefunc)(typeofargument)?只有这件事。只是代码少了还是我错了?
@wisepeople 你忽略了一个事实,你只是使用function_name(args)
你被那个功能困住了。通过传递一个函数作为参数,调用者可以改变调用函数的选择。这与传递 int
参数而不是在函数体中硬编码一个整数没有什么不同。
【参考方案1】:
如果您希望函数根据用户的需要做不同的事情,您可以使用函数指针作为参数。
这是一个简单的例子:
#include <stdio.h>
int add(int x, int y)
return x + y;
int subtract(int x, int y)
return x - y;
int multiply(int x, int y)
return x * y;
int divide(int x, int y)
return x / y;
int operation(int x, int y, int (*func)(int, int))
printf(" x=%d, y=%d\n", x, y);
return func(x,y);
int main()
int x = 8, y = 4;
printf("x+y=%d\n", operation(x,y,add));
printf("x-y=%d\n", operation(x,y,subtract));
printf("x*y=%d\n", operation(x,y,multiply));
printf("x/y=%d\n", operation(x,y,divide));
return 0;
【讨论】:
【参考方案2】:一个很好的例子是经典的排序功能qsort
。这是一个库函数,这意味着您只能访问它的原型。为了使qsort
通用,您必须编写自己的比较函数。常规整数的典型实现如下所示:
int cmpfunc (const void * a, const void * b)
return ( *(int*)a - *(int*)b );
然后,如果您有一个整数数组 arr
,您可以使用 qsort(arr, sizeof(arr), cmpfunc)
对其进行排序
你可能会问为什么这不是在qsort
函数中内置的?毕竟,很容易让它同时适用于浮点数和整数。是的,但是想象一下,如果你有一个结构数组,看起来像这样:
struct
char *firstname;
char *lastname;
int age;
persons[10];
你会如何排序?嗯,这并不明显。你可能想要这三个。在这种情况下,编写三个不同的比较函数。
【讨论】:
【参考方案3】:我只想知道为什么你用这个而不是:void map (int (*fun) (int),int x[ ], int l) for(i = 0; i < l; i++) x[i] = fun(x[i]);
void map (int x[ ], int l) for(i = 0; i < l; i++) x[i] = nameoffunction(yourargument);
让我们用一个问题来回答这个问题 - 如果您想要执行不止一种类型的映射怎么办?如果你想同时映射 x2 和 √x 怎么办?
你当然可以做类似的事情
void map( int x[], int l, int type )
for ( int i = 0; i < l; i++ )
if ( type == MAP_SQUARED )
x[i] = int_square( x );
else if ( type == MAP_ROOT )
x[i] = int_root( x );
...
这可行,但难以阅读且维护麻烦 - 每次您想要执行新映射时,都必须向 map
函数添加一个新案例。
对比一下
void map( int x[], int l, int (*fun)(int) )
for ( int i = 0; i < l; i++ )
x[i] = fun( x[i] );
...
map( x, l, int_square );
map( y, l, int_root );
您不必破解 map
函数来获得不同的映射 - 您只需传递对单个元素进行操作的函数。如果你想执行一个新的映射,你所要做的就是编写一个新函数——你根本不需要编辑map
函数。
C 标准库在多个地方使用这种形式的委托,包括 qsort
函数(允许您以任何顺序对任何类型的数组进行排序)和 signal
函数(允许您更改程序的反应方式)动态中断)。
【讨论】:
以上是关于为啥将函数作为函数的参数传递?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我们将视图和上下文对象作为函数中的参数传递,API 22 [关闭]