我从c中的标准库中读取了一个mergeSort,发现它有一个比较函数作为参数(即定义时的void msort(void*base,size_t nitems,size _t size,int(*compar((const void,const void(((。然而,在实际使用中,当调用msort函数时,compar函数没有向其传递参数(尽管它有两个参数,它们是(const void*,const void*(作为参数。看看ff代码片段,我会很感激在调用带有参数的函数时,如何在没有参数的情况下使用它??
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main () {
int n;
printf("Before sorting the list is: n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
msort(values, 5, sizeof(int), cmpfunc);
printf("nAfter sorting the list is: n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
这是一个所谓的函数指针:您基本上是将函数cmpfunc()
作为参数传递,然后msort()
函数将在内部使用该参数,并使用适当的参数。
函数指针是一个变量,用于存储稍后可以通过该函数指针调用的函数的地址。这很有用,因为函数封装了行为。
函数指针是函数闭包的前兆。
更清楚地说:它没有参数的原因是因为你还不知道它们
让我解释一下:cmpfunc()
用于比较两个元素,并判断哪个元素在另一个元素之前。但是msort()
需要进行许多不同的比较,因为它必须迭代values[]
的所有元素。因此,在内部msort()
将一次选择2个元素,让我们将它们称为x
和y
,比较它们cmpfunc(x, y)
,并在需要时交换它们。
void msort(void *base, size_t nitems, size_t size, int (*compar)(const void* , const void*))
函数msort
将函数指针作为其最终参数。就像常规的参数一样,这个参数告诉msort
函数;本身以两个CCD_ 12为自变量并重新运行CCD_;将作为参数传递。调用时类似:
msort(values, 5, sizeof(int), cmpfunc);
如果没有cmpfunc
末尾的paranostics,您只是传递cmpfunc
的地址,而不是实际调用它,因此无论如何传递参数都没有意义。您只是告诉msort
在哪里可以找到函数。
真正调用cmpfunc
的是msort
。如果您可以访问它的源代码,您可能可以看到它何时以及如何调用它(传递适当的参数(。
我不会重复别人正确描述的"将函数的地址作为参数传递给另一个函数">
A";用例";可以帮助您理解"为什么">
从你的例子来看:
int cmpAscending (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
现在;双";其中:
int cmpDescending (const void * a, const void * b) {
return ( *(int*)b - *(int*)a ); // NB: subtle difference
}
现在,程序可以将适当的比较函数的地址传递给msort()
。
if( ascending )
msort( values, 5, sizeof(int), cmpAscending );
else
msort( values, 5, sizeof(int), cmpDescending );
还有更经济的方法可以实现这一点:
msort( values, 5, sizeof(int), ascending ? cmpAscending : cmpDescending );
例如,在主函数中,foo接收bar函数的地址。然后函数foo可以通过它作为参数接收的函数指针pbar调用函数栏:
#include <stdio.h>
void bar(int x )
{
printf("%dn", x);
}
void foo(void(*pbar)(int))
{
pbar(10);
pbar(20);
}
int main(void)
{
foo(bar);
return(0);
}