在了解形式之前,我们需要知道一个小细节
自定义函数名和取地址函数名是等价的
void test()
{
return;
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
}
所以我们书写就会有两种形式:
void (*pf1)() = &test;
void (*pf2)()= test;
如果函数需要传参,返回值,则括号里要表达形式
int Add(int x, int y)
{
return x+y;
}
int (*pf3) (int x,int y)
//也可以省略x,y
int (*pf4) (int ,int )
通过直接解引用,并且传参就可以直接调用
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (*pf1) (int, int) = Add;
//直接调用
printf("%d\n", Add(1, 8));
//指针解引用
printf("%d\n", (*pf1)(1, 8));
}
虽然函数可以全局调用,但是有时候我们需要在程序运行时动态地确定调用哪个函数,或者需要将函数作为参数传递给其他函数。这时候就需要使用函数指针作为参数。
函数指针数组是一个数组,其中的每个元素都是一个函数指针。函数指针数组可以用来存储多个函数的地址,从而可以根据需要动态地选择并调用不同的函数。
形式如下:
void (*functions[2])() = {function1, function2};
我们接下来展示一段简易代码,利用函数指针数组做一个转移表实行计算器的部分功能:
int Add(int x, int y)
{
return x + y;
}
int Mul(int x, int y)
{
return x * y;
}
int Sub(int x, int y)
{
return x - y;
}
int Div(int x, int y)
{
return x / y;
}
int main()
{
int x, y;
int input = 1;
//将函数封装进数组
int(*p[5]) (int, int) = { NULL,Add,Mul,Sub,Div };
//打印菜单
do {
printf("***************************\n");
printf("***************************\n");
printf("****0:退出 1:加法 ******\n");
printf("****2:乘法 3:减法 ******\n");
printf("****4:除法 ******\n");
printf("***************************\n");
printf("***************************\n");
scanf("%d", &input);
if (input<5&&input>0)
{
printf("请输入你要计算的数字x,y\n");
scanf("%d %d", &x, &y);
int ret =(p[input](x, y));//调用
printf("结果是:%d\n",ret );
}
else break;
} while (input);
return 0;
}
由此我们可知相同参数和类型近似的函数可以通过函数指针数组分装使用
回调函数是指在某个函数执行过程中,通过函数指针调用另一个函数的过程。通常情况下,回调函数作为参数传递给某个函数,并在该函数特定的条件下被调用。
回调函数通常用于实现一些灵活的、可定制的功能,例如事件处理、状态通知、数据处理等。通过回调函数,可以将特定的处理逻辑从原始函数中分离出来,使得原始函数具有更高的通用性和灵活性。
在c语言中有一个经典的库函数qsort,它的底层逻辑是快速排序,他需要用户自己实现比较部分函数
void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *));
四个参数分别为:
1.void *base:指向待排序数组的指针,即数组的首元素地址。
qsort 函数通过这个指针来访问待排序的元素。
2.size_t num:数组中待排序元素的个数。
3.size_t size:每个元素的大小(以字节为单位)。
由于 qsort 函数不知道数组中元素的具体类型,
因此需要通过 size 参数来确定每个元素的大小。
4.int (*compar)(const void *, const void *):指向比较函数的指针。
比较函数的原型必须是 int compar(const void *a, const void *b),
其中 a 和 b 是待比较的两个元素的指针。
比较函数需要根据实际的排序需求来定义,
返回值为负数表示 a 应该排在 b 前面,
返回值为正数表示 a 应该排在 b 后面,
返回值为 0 表示 a 和 b 相等。
展示一个简单排序:
int compare(const void* a, const void* b)
{
return *((int*)a) - *((int*)b);
}
int main()
{
int arr[10] = { 2,5,7,4,6,1,5,0,9,7 };
//排序
qsort(arr, 10, sizeof(int), compare);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
不光是整形排序,void类型意味着可以兼容各种数据的排序。
本期的知识分享到此结束。希望三联支持一下博主!