【C语言】指针详解(3)

大家好,我是苏貝,本篇博客带大家了解指针(2),如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️


目录

一.函数指针数组

字符数组--数组--存放字符的数组

整型数组--数组--存放整型的数组

指针数组--数组--存放指针的数组

函数指针数组--数组--存放函数指针的数组,即存放函数的地址

int (* parr1[10])();

parr1 先和 [ ] 结合,说明 parr1是数组,数组的元素类型是什么呢?将数组名和数组名后面的[ ] 去掉,得到int (* )(),即函数指针,所以数组的元素类型是函数指针

函数指针数组的用途:转移表

例子:计算器,实现+ - * / 4个功能

c 复制代码
#include<stdio.h>

void menu()
{
	printf("********************************\n");
	printf("******   1.Add   2.Sub    ******\n");
	printf("******   3.Mul   4.Div    ******\n");
	printf("******   0.exit           ******\n");
	printf("********************************\n");
}

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;
}

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入2个数:");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf("请输入2个数:");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入2个数:");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入2个数:");
			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;
}

但是写完这些代码后我们发现,这些代码有许多重复的地方,所以我们是否可以简化一下呢?

简化上面的代码,我们发现,Add,Sub,Mul,Div的参数类型和个数相同,返回类型也相同,所以可以使用函数指针数组,让Add,Sub,Mul,Div成为该数组的元素,用数组的元素调用Add,Sub,Mul,Div函数;

int(*pfArr [ ])(int, int) = { Add,Sub,Mul,Div };

所以它们的下标分别为0,1,2,3,但由于菜单上1,2,3,4才代表它们,所以我们不妨在Add前加NULL,这样它们的下标就为1,2,3,4了

int(*pfArr[])(int, int) = { NULL,Add,Sub,Mul,Div };

总代码:

c 复制代码
#include<stdio.h>

void menu()
{
	printf("********************************\n");
	printf("******   1.Add   2.Sub    ******\n");
	printf("******   3.Mul   4.Div    ******\n");
	printf("******   0.exit           ******\n");
	printf("********************************\n");
}

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;
}

int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		int(*pfArr[])(int, int) = { NULL,Add,Sub,Mul,Div };
		if (0 == input)
			printf("退出程序\n");
		else if (input >= 1 && input <= 4)
		{
			printf("请输入2个数:");
			scanf("%d %d", &x, &y);
			ret = pfArr[input](x, y);
			printf("%d\n", ret);
		}
		else
			printf("输入错误,请重新输入\n");
	} while (input);
	return 0;
}

上述代码也有缺陷,因为要写成数组元素的话,它们的类型必须要相同,如果有一个函数,它的返回类型不是int,那就不能采用这种方法

二.指向函数指针数组的指针(不重要)

经过上面的学习,我们可以知道,指向函数指针数组的指针是一个 指针 ,指针指向一个 数组 ,数组的元素都是 函数指针,那指向函数指针数组的指针该如何定义呢?

void(*(*p)[2])(int, int);

p先与 * 结合,代表p是个指针,再与[ ]结合,表示p指向的是个数组,将( * p)[2]去掉得到void( *)(int, int)是函数指针,所以数组的元素类型是函数指针

c 复制代码
int Add(int x, int y)
{
	return x + y;
}

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

int main()
{
	//函数指针
	int (*pf)(int, int) = Add;
	//函数指针数组
	int (*pfArr[2])(int, int) = { Add,Sub };
	//指向函数指针数组的指针
	int(*(*p)[2])(int, int);
	return 0;
}

三.回调函数

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

例子:计算器(将上面最开始的计数器代码优化)

我们可以看出,上面红色框里面的大部分代码都冗余,那我们能否使用一个函数cacl()达到实现+ - * / 4个功能的目的呢?

思路:将实现+ - * / 4个功能的函数作为函数cacl()的形参,用一个函数指针来接收

c 复制代码
void menu()
{
	printf("********************************\n");
	printf("******   1.Add   2.Sub    ******\n");
	printf("******   3.Mul   4.Div    ******\n");
	printf("******   0.exit           ******\n");
	printf("********************************\n");
}

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 cacl(int (*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("请输入2个数:");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			cacl(Add);
			break;
		case 2:
			cacl(Sub);
			break;
		case 3:
			cacl(Mul);
			break;
		case 4:
			cacl(Div);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误,请重新选择:\n");
			break;
		}
	} while (input);
	return 0;
}

先使input==2,所以选择的是减法,输入使得x=10,y=2,通过函数指针pf找到Sub函数,返回8用ret接收,最后输出ret


好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️

相关推荐
superxxd1 小时前
跨平台音频IO处理库libsoundio实践
开发语言·qt·音视频
海洲探索-Hydrovo2 小时前
TTP Aether X 天通透传模块丨国产自主可控大数据双向通讯定位模组
网络·人工智能·科技·算法·信息与通信
_OP_CHEN2 小时前
C++基础:(十二)list类的基础使用
开发语言·数据结构·c++·stl·list类·list核心接口·list底层原理
2401_841495645 小时前
【计算机视觉】基于复杂环境下的车牌识别
人工智能·python·算法·计算机视觉·去噪·车牌识别·字符识别
Jonkin-Ma5 小时前
每日算法(1)之单链表
算法
ONE_PUNCH_Ge5 小时前
Go 语言变量
开发语言
幼稚园的山代王5 小时前
go语言了解
开发语言·后端·golang
奔跑吧邓邓子5 小时前
【C语言实战(8)】C语言循环结构(do-while):解锁编程新境界
c语言·实战·do-while
晚风残5 小时前
【C++ Primer】第六章:函数
开发语言·c++·算法·c++ primer
小莞尔6 小时前
【51单片机】【protues仿真】基于51单片机温度测量系统
c语言·单片机·嵌入式硬件·物联网·51单片机