特征(4):函数指针有什么用

总结卡片:
函数指针有什么用
指针意味着共享,一个函数产生的指针,在另一个函数中可以使用,大家访问着同一块内存,所以,指针(或地址)是函数间交互的一个办法。
有一类指针叫函数指针。函数指针指向函数,比如,如果pf是一个函数指针,那么pf就是函数,通过pf就能完成函数的调用,而不需要知道原函数的名字。函数指针是一个变量,可存放函数地址,而函数名就是函数地址,比如:

#include <stdio.h>
int add(int a, int b) {
	return a+b;
}
int add2(int a, int b) {
	return 10*a+b;
}
int main() {
	int (*pf)(int a, int b);
	pf=add;
	printf("add:%d\n", (*pf)(100,200));
	pf=add2;
	printf("add2:%d\n", (*pf)(100,200));
	return 0;
}

如果事先知道某个函数的声明或实现,那么在你写的函数中就可以调用它;如果事先并不知道某个函数的声明,或者还没有某个函数的实现,那从设计的角度,你也可以通过函数指针,设计出这个函数的样子,也就是接口的设计。
比如,我要写一个函数,把当前的时间按某个格式打印出来,我的函数可以拿到当前的时间,但这个时间用什么格式来表达(表达成什么样子)我是不知道的,我的函数要依赖于别人的实现,但别人的实现还没有声明,那这时,我就可以通过函数指针,先设计出按某个格式返回字符串的函数的声明,也就是设计了一个接口,之后别人实现这个接口就可以了。

// hello1.c
#include <stdio.h>
typedef char* (*TIME_FUNC)(char* time);
TIME_FUNC g_timeformat;
extern void init();
int main() {
	init();
	char* nowtime="2022-02-10 15:20:42";
	printf("%s\n", (*g_timeformat)(nowtime));
	return 0;
}

上面设计了一个函数指针g_timeformat,在另一个文件中对这个函数指针进行了赋值:

// hello2.c
char* mytime(char* time) {
	return time;
}
typedef char* (*TIME_FUNC)(char* time);
extern TIME_FUNC g_timeformat;
void init() {
	g_timeformat = mytime;
}

同时cc这两个文件就可以运行起来。
以上在函数体内调用了别人实现的函数指针,而另一种常见的做法,是在函数的参数中设置函数指针,以达到交互的目的。
比如,C提供了快速排序的库函数叫qsort,qsort在排序过程需要频繁地两两比较,而这个比较的行为被qsort独立出来了,qsort不实现,由调用qsort的模块来实现以定义怎么样才叫做“大于”或“小于”。qsort在排序过程中要调用到别的模块的比较的实现,考虑到这一点,qsort函数的原型设计成这样:
void qsort(void base, size_t nitems, size_t size, int (compar)(const void , const void))
最后一个参数是函数指针,指向的函数要实现两两比较的行为。qsort函数通过函数指针,达到与外界交互的目的。
比如,可以这样调用qsort函数,注意自行实现比较函数:

#include <stdio.h>
#include <stdlib.h>
int mycompare(const void* l, const void* r) {
	return *((const int*)l) - *((const int*)r);
}
int main() {
	int arr[] = {23,100,1,2,90,3,0,-1,-35,199,-1};
	int cnt = sizeof arr / sizeof *arr;
	printf("before sort:\n");
	for(int i=0;i<cnt;i++) printf("%d、",arr[i]);
	printf("\nafter sort:\n");
	qsort(arr, cnt, sizeof *arr, mycompare);
	for(int i=0;i<cnt;i++) printf("%d、",arr[i]);
	printf("\n");
	return 0;
}

qsort执行效果
qsort函数在参数的设计上体现了交互的一种方式,也是函数指针的一种使用场景。

Tags: