C中函数的指针

C中函数的指针,c,C,我觉得我对C语言中的指针有很好的处理能力 它们将数组传递给函数 但我注意到,在查看许多不同的代码示例时,发现 请参阅指向函数的指针。我一点也不清楚为什么这会有用? 是否有一些经典的例子,其中指向函数模型的指针是方便的或实现起来必不可少的?经典的例子是使用。它的最后一个参数是一个函数指针,指向比较两个元素的例程,作为空指针传递 void qsort(void*base, 尺寸(mm), 大小, int(*比较)(常数无效*,常数无效*); 在这里使用函数指针是必要的,因为排序例程不能变得足够通用

我觉得我对C语言中的指针有很好的处理能力 它们将数组传递给函数

但我注意到,在查看许多不同的代码示例时,发现 请参阅指向函数的指针。我一点也不清楚为什么这会有用?
是否有一些经典的例子,其中指向函数模型的指针是方便的或实现起来必不可少的?

经典的例子是使用。它的最后一个参数是一个函数指针,指向比较两个元素的例程,作为空指针传递

void qsort(void*base,
尺寸(mm),
大小,
int(*比较)(常数无效*,常数无效*);
在这里使用函数指针是必要的,因为排序例程不能变得足够通用,无法知道如何比较元素,因此函数指针本质上是一个“回调”,排序函数使用它来扩展它

[Edit]例如,假设您定义了以下结构:

struct-president{
char*fname;
char*lname;
无符号整数;
};
如果您想按“数字”字段对它们的数组进行排序,可以实现一个“比较器”(comparator)函数,如下所示:

int比较(常量无效*v1,常量无效*v2){
结构主席p1=*((结构主席*)v1);
结构主席p2=*((结构主席*)v2);
return(p1.number-p2.number);//按数字升序进行比较。
}
您可以对这样的结构数组进行如下排序:

qsort(总裁、总裁数量、结构总裁大小、比较总裁);

将指向函数的指针看作是实现(好的,描述)我们现在优雅地称之为回调的“石头刀和熊皮”方式。这个类比并不完美,但正是这个想法——提供了一种通过指针引用调用完全不同的函数的快速但相当危险的方法。

一个明显的例子是
qsort
。您向它传递一个指向将用于比较项的函数的指针。因为它不知道您要排序的是哪种数据,所以它无法单独完成这一部分


另一个常见的例子是进行数值积分的函数。您向它传递一个指向要集成的函数的指针,以及下限和上限,然后它调用该函数以查找这些边界之间的各个点的值,从而得到您的答案。

示例1:假设有5种不同的排序算法。您只想在各种地方进行排序,但不想在每个地方的5个和每个地方进行选择。相反,您有一个指向排序算法的指针(它们都采用相同的参数、类型等)。只需选择一次算法(设置指针),然后使用指针到处排序


示例2:回调。。。函数在循环中执行某些操作,但每次迭代都需要应用程序反馈。对于该函数,回调是作为参数传递的函数指针。

非常常见的用法是用于事件处理程序的回调函数。例如,设想一个按钮按下处理程序。您的按钮\u update()可能看起来像:

void button_update(struct button* button, void* data) {
    if (button_pressed(button)) {
        button.callback(data);
    }
}

在本例中,button.callback将是一个函数指针。

启动线程是另一个示例。与POSIX类似,C11具有启动线程的接口:

typedef int (*thrd_start_t)(void*);
int thrd_create(thrd_t *, thrd_start_t, void *);

这里的
thrd\u start\t
函数指针指向将由新线程执行的函数,
void*
参数是传递给该函数的参数。

还有一个例子是一些重载系统编程或实时嵌入式编程。处理器中断向量表可以实现为函数指针数组。它们是在汇编程序中以这种方式实现的,如果您有一种(非C标准)指定函数表内存位置的方法,也可以用C来实现。

函数指针的另一个常见用例是插件。插件可以实现为可动态加载的库。当应用程序加载插件时,它可以调用预定义的函数,传入带有应用程序函数指针的结构,然后返回带有插件函数指针的结构。现在,插件和应用程序可以互相调用函数。

甚至更多:函数指针也有函数签名给出的类型。 您还可以[小心地]转换为特定的函数指针类型:

在qsort示例中,预期比较器在签名中具有const void*:

int(*比较器)(常量无效*,常量无效*)

但是,如果您有一个针对特定(非void*)ptr类型的比较函数,则可以将其转换为qsort预期签名:

(int(*)(const void*,const void*)特定于cmpr的

类似地,typedef可用于定义函数指针的签名,从而省去计算参数的痛苦:

typedef int(*MYFUNC_T)(int-arg)
MYFUNC\u T callptr=MYFUNC;callptr(10)

,其中myfunc是具体的
int-myfunc(int-arg)

现在想想它的定义是什么:
int(*fptr_arr[10])(int(*)(int))

好的,typedef使其易读:
typedefint(*FUNC_T)(intarg);typedef int(*FUNC2_T)(FUNC_T FUNC)--接受函数指针参数的函数


FUNC2_T fptr_arr[10];fptr_arr[0]=myfunc

qsort()
是使用函数指针的示例。这允许基于不同的标准(和类型)使用相同的排序算法。@cnicutar
sqrt
?@erregrith它是如何声明的?它如何比较元素?--我的意思是
qsort
@cnicutar,你把
qsort
误认为是
sqrt
sqrt
是平方根函数。@没错,很抱歉:-)