指针进阶·函数指针、函数指针数组、指向函数指针数组的指针(三)

本文详细介绍了函数指针的使用,从理解函数地址、函数指针的定义和调用,到如何通过函数指针改进代码结构,如在计算器程序中的应用。进一步讨论了函数指针数组和指向函数指针数组的指针的概念,以及回调函数的基本思想。通过实例展示了如何利用函数指针简化代码并提高可维护性。
摘要由CSDN通过智能技术生成

目录

理解函数

函数指针的用途

用法 

 函数指针的常规使用

计算机修改前 

利用函数指针修改后

函数指针的数组 

 ​加入函数指针完善后

指向函数指针数组的指针

分析 

回调函数

​​​​​​​​概念

结束语


指针有很多种用法,这里我们来讲解其中的一个 函数指针 的使用

理解函数

​//函数指针

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}

int main() {
	
	printf("%p\n",Add);
	printf("%p\n",&Add);
	//通过这两个地址来说明,&函数名和函数名都是函数的地址
	return 0;
}

运行通过后发现函数是有自己的地址,我们需要知道的是函数的地址是在编译的时候就已经分好空间 ,并有了地址。注意的是这里的 &Add Add 是一个意思

函数指针的用途

类似与整型、字符、数组等类型的指针一样,我们可以通过指针来找到函数并使用函数

用法 

​//函数指针的使用

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}

int main() {
	int (*pf)(int, int) = &Add;

	//int ret = Add(2,3);   //函数调用的形式

	int ret = (*pf)(2,3);	//函数指针的一般形式

	//int ret = pf(2, 3);	//函数指针缩写形式

	printf("%d\n",ret);
	return 0;
}

函数指针的常规使用

 

通过一个简单的计算器来讲解函数指针的用途

计算机修改前 

 

​
//一个简单的计算器
#include<stdio.h>
int add(int x, int y)
{
	return x + y;
}

int sub(int x, int y)
{
	return x - y;
}

int mul(int x, int y)
{
	return x * y;
}

int div(int x, int y)
{
	return x / y;
}

void menu() {
	printf("*********************\n");
	printf("**  1.add   2.sub  **\n");
	printf("**  3.mul   4.div  **\n");
	printf("**  0.exit         **\n");
	printf("*********************\n");	
}
int main() {


		int x = 0;
		int y = 0;
		int input = 0;
		int ret = 0;
		do
		{
        menu();
		printf("请选择:>");
		scanf("%d", &input);
			switch (input)
			{
			case 1:
				printf("请输入两个数:>");
				scanf("%d %d", &x, &y);
				ret = add(x, y);
				printf("%d\n", ret);
				break;
			case 2:
				printf("请输入两个数:>");
				scanf("%d %d", &x, &y);
				ret = sub(x, y);
				printf("%d\n", ret);
				break;
			case 3:
				printf("请输入两个数:>");
				scanf("%d %d", &x, &y);
				ret = mul(x, y);
				printf("%d\n", ret);
				break;
			case 4:
				printf("请输入两个数:>");
				scanf("%d %d", &x, &y);
				ret = div(x, y);
				printf("%d\n", ret);
				break;
			case 0:
				printf("退出计算器\n");
				break;
			default:
				printf("选择错误\n");
				break;
			}
		} while (input);

	return 0;
}

​

 

为此我们利用函数指针可以进行改良

利用函数指针修改后

​
//修改后
#include<stdio.h>
int add(int x, int y)
{
	return x + y;
}

int sub(int x, int y)
{
	return x - y;
}

int mul(int x, int y)
{
	return x * y;
}

int div(int x, int y)
{
	return x / y;
}

void cal(int (*pf)(int, int)) {
	int x = 0;
	int y = 0;
	printf("请输入两个数:>");
	scanf("%d %d", &x, &y);
	int ret = pf(x, y);
	printf("%d\n", ret);
}

void menu() {
	printf("*********************\n");
	printf("**  1.add   2.sub  **\n");
	printf("**  3.mul   4.div  **\n");
	printf("**  0.exit         **\n");
	printf("*********************\n");
}

int main() {


	int input = 0;
	do
	{
	    menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			cal(add);
			break;
		case 2:
			cal(sub);
			break;
		case 3:
			cal(mul);
			break;
		case 4:
			cal(div);
			break;
		case 0:
			printf("退出计算器\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);

	return 0;
}

​

 

这种方式我们称之为 回调函数,在文章的最后我会说明简单介绍一下回调函数的概念

函数指针的数组 

当我们把计算器的功能逐步完善,添加新的功能的时候会发现,代码会越写越长,因此我们可以再进一步,使用函数指针的数组来进行进一步简化

//函数指针的数组
#include<stdio.h>
int add(int x, int y)
{
	return x + y;
}

int sub(int x, int y)
{
	return x - y;
}

int mul(int x, int y)
{
	return x * y;
}

int div(int x, int y)
{
	return x / y;
}

void menu() {
	printf("*********************\n");
	printf("**  1.add   2.sub  **\n");
	printf("**  3.mul   4.div  **\n");
	printf("**  0.exit         **\n");
	printf("*********************\n");
}
int main() {

	int x = 0;
	int y = 0;
	int input = 0;
	int ret = 0;

	int (*pfarr[])(int, int) = { 0, add, sub, mul, div };//将数组下标向后移动一个和menu相应
	int sz = sizeof(pfarr) / sizeof(pfarr[0]);    //计算数组的个数

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		if (0 == input)
		{
			printf("退出计算器\n");
		}
		else if (input >= 1 && input <= sz)
		{
			printf("请输入两个数:>");     //同样的这里我们也可以使用函数指针的方式进一步改善
			scanf("%d %d", &x, &y);      //这里为了便于理解,使用了这种用法
			ret = pfarr[input](x, y);
			printf("%d\n", ret);
		}
		else
		{
			printf("选择错误\n");
		}

	} while (input);

	return 0;
}

 加入函数指针完善后

//加入函数指针进行封装函数
#include<stdio.h>
int add(int x, int y)
{
	return x + y;
}

int sub(int x, int y)
{
	return x - y;
}

int mul(int x, int y)
{
	return x * y;
}

int div(int x, int y)
{
	return x / y;
}

void cal(int (*pf)(int, int)) {
	int x = 0;
	int y = 0;
	printf("请输入两个数:>");
	scanf("%d %d", &x, &y);
	int ret = pf(x, y);
	printf("%d\n", ret);
}

void menu() {
	printf("*********************\n");
	printf("**  1.add   2.sub  **\n");
	printf("**  3.mul   4.div  **\n");
	printf("**  0.exit         **\n");
	printf("*********************\n");
}
int main() {

	int x = 0;
	int y = 0;
	int input = 0;
	int ret = 0;

	int (*pfarr[])(int, int) = { 0, add, sub, mul, div };
	int sz = sizeof(pfarr) / sizeof(pfarr[0]);

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		if (0 == input)
		{
			printf("退出计算器\n");
		}
		else if (input >=1 && input<=sz)
		{
			cal(pfarr[input]);    //传过去一个函数地址
		}
		else
		{
			printf("选择错误\n");
		}

	} while (input);

	return 0;
}

通过以上的案例我们可以知道,代码的形式有千千万万,形同的目标可能一千个程序员就有一千个不同的代码。我们需要明白这一点,脚踏实地的做好应该做的,提升自己,这样遇到的困难就会少一点,自己的能力也就上去了

指向函数指针数组的指针

int main() {
    //函数指针数组
    int  ( *pfarr[ ] )( int , int ) = { 0 , add , sub , mul , div };

    //指向 函数指针数组的 指针
    int  ( * ( * ppfarr )[5] ) ( int , int ) = &pfarr;

    return 0;
}

分析 

1.首先 ppfarr 是一个指针,因此要 ( * ppfarr ) 表明为指针

2.再者,ppfaar 指向了一个数组 ( * ppfarr )[5] ,这样就可以表示是一个指向数组的指针

3.最后 ppfaar 的类型是把 ( * ppfarr )[5]去掉,剩下的部分 int  ( *  ) ( int , int ),即函数指针的类型

回调函数

概念

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

关于回调函数的具体实现我会在下一篇文章中详解,这里只是提一下

结束语

                                                        高处不胜景

其实视野的开阔与否,得到的东西也会随之不同,信息是当今最不珍贵的东西,却是最有用的东西,这就和站的高看得远一样,站在高处,你只会仰视看向更高的、更远的地方,而低处俯看……

未完持续更新中…… 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风玉骨

爱了!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值