函数指针和回调函数

文章目录

一.函数指针

1.什么是函数指针

  • 函数指针是指向函数的指针。在C语言和C++中,函数指针可以用来存储函数的地址,并且可以通过函数指针来调用函数。
  • 也可以作为函数的返回值。通过函数指针,可以实现回调函数和动态函数调用等功能。
  • 通过函数指针,可以实现回调函数和动态函数调用等功能。函数指针的类型由函数的参数和返回值类型来确定。函数指针在一些高级的编程技术中经常被使用,例如函数指针数组、函数指针作为结构体成员等。

2.函数指针的形式

在了解形式之前,我们需要知道一个小细节
自定义函数名和取地址函数名是等价的

c 复制代码
void test()
{
	return;
}
int main()
{
	printf("%p\n", test);
	printf("%p\n", &test);
}


所以我们书写就会有两种形式:

void (*pf1)() = &test;
void (*pf2)()= test;

如果函数需要传参,返回值,则括号里要表达形式

c 复制代码
int Add(int x, int y)
{
return x+y;
}
int (*pf3) (int x,int y)
//也可以省略x,y
int (*pf4) (int ,int )

3.函数指针的用途。

1.调用函数

通过直接解引用,并且传参就可以直接调用

c 复制代码
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));
}

2.作为参数进行传递

虽然函数可以全局调用,但是有时候我们需要在程序运行时动态地确定调用哪个函数,或者需要将函数作为参数传递给其他函数。这时候就需要使用函数指针作为参数。

二.函数指针数组

函数指针数组是一个数组,其中的每个元素都是一个函数指针。函数指针数组可以用来存储多个函数的地址,从而可以根据需要动态地选择并调用不同的函数。

形式如下:

c 复制代码
void (*functions[2])() = {function1, function2};

我们接下来展示一段简易代码,利用函数指针数组做一个转移表实行计算器的部分功能:

c 复制代码
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 相等。

展示一个简单排序:

c 复制代码
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类型意味着可以兼容各种数据的排序。

本期的知识分享到此结束。希望三联支持一下博主!

相关推荐
vortex55 分钟前
解决 VSCode 中 C/C++ 编码乱码问题的两种方法
c语言·c++·vscode
Xiao Fei Xiangζั͡ޓއއ26 分钟前
一觉睡醒,全世界计算机水平下降100倍,而我却精通C语言——scanf函数
c语言·开发语言·笔记·程序人生·面试·蓝桥杯·学习方法
baijin_cha44 分钟前
机器学习基础04_朴素贝叶斯分类&决策树分类
笔记·决策树·机器学习·分类
子朔不言1 小时前
[ARM-2D 专题]6.脏矩形定义的宏使用技巧和分析
c语言·arm开发·arm2d·显控开发-新龙微
波克比QWQ1 小时前
rust逆向初探
笔记·rust逆向
LuckyLay1 小时前
Spring学习笔记_36——@RequestMapping
java·spring boot·笔记·spring·mapping
坚硬果壳_1 小时前
《硬件架构的艺术》笔记(一):亚稳态
笔记·学习
BT-BOX2 小时前
STM32仿真proteus位带操作和keil增加头文件C文件
c语言·stm32·proteus
醉颜凉2 小时前
【NOIP提高组】潜伏者
java·c语言·开发语言·c++·算法
qiyi.sky2 小时前
JavaWeb——Web入门(8/9)- Tomcat:基本使用(下载与安装、目录结构介绍、启动与关闭、可能出现的问题及解决方案、总结)
java·前端·笔记·学习·tomcat