函数指针及函数指针的夹层外套

目录

函数指针的类型与使用

解读函数指针

代码一

代码二

函数指针数组

使用

指向函数指针数组的指针


函数其实也是有地址的,函数名就是函数的地址,&函数名也是函数的地址。所以就存在函数指针,而有了函数指针就有函数指针数组,那有了函数指针数组,不就又有了指向函数指针数组的指针了嘛,这不就成了套娃吗。

函数指针的类型与使用

首先知道它是一个指针所以就(*p)表示指针,其它就是照搬函数类型了。而使用方法就可类似函数的形式。

#include<stdio.h>
int Max(int x, int y)
{
	return (x > y ? x : y);
}
int main() 
{
	int a, b;
	scanf("%d%d", &a, &b);
	int(*p)(int ,int) = Max;//函数名就是地址,p指向Max地址
	//函数类型是int (int ,int)
    //函数指针变量p的类型就是int (*)(int ,int)

	//使用:
	int ret = (*p)(a, b);//这里(*p)就相当于Max函数
	printf("%d", ret);

	return 0;
}

 其实在你编译的时候 int ret=(*p)(a,b) 中的 * 也是可以省略的,不影响结果,p实际指向的就是Max函数。 (主要还是由于函数名与&函数名都表示函数的地址,所以就有这种效果,即:不管你前面有多少*操作都不影响执行,所以 * 就如同摆设)

解读函数指针

代码一

(*( void(*)() )0)()

 先分析,从里向外看,void(*)() 这不就是函数指针类型嘛,是无参且无返回值的函数指针类型,然后就被括起来加了个0,0是一个int类型的数,前面部分不就相当于强制类型转换嘛,将int(0)强制类型转换成函数指针类型,相当于0地址处放一个无参无返回值的函数,外面解引用加个空括号,那不就是调用0地址处的函数嘛。

代码二

void(* signal(int,void(*)(int)))(int)

同代码一的分析,先看里面的 signal(int,void(*)(int)) 不就是一个signal 的函数嘛,一个参数是int 类型,另一个参数是void(*)(int)函数指针类型,此时是不是就想到函数还差的一个部分(返回类型)呢,确实外面部分的void(*)(int)就是函数signal的返回类型,而返回类型也是一个函数指针,那为什么会分开写呢?返回类型 void(*)(int)不应该写在前面嘛。所以这就是函数的声明。

当我们使用 typdef 进行类型的重命名时,名字必须写在*的后面。

1.typedef void(*)(int) typ_t//这种就无法执行下去

2.typedef void(*typ_t)(int) //将void(*)(int)重命名为typ_t这个类型名

函数指针数组

见名知意,函数指针数组就是存放函数指针的数组。假如我们现在有几个相同返回值和参数的函数,那么我们就可以用函数指针数组存放起来。

#include<stdio.h>
int sum(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 (*p[4])(int, int) = { sum,sub,mul,div };//创建函数指针数组,p[4]就是表示数组,
//其余分就是函数指针数组的类型,因为这四个函数的类型(参数与返回值)是一样的才可以放在一起。

	return 0;
}

使用

写一段代码,可以同时进行加减乘除?

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 input = 0;
	int x = 0;
	int y = 0;

	//转移表 - 函数指针的数组
	int (*pfArr[])(int, int) = {NULL, Add, Sub, Mul, Div};//创建函数指针数组放置这几个函数的地址,数组首元素放个NULL为了占据一个位置,方便后续的循环执行。
	                           //0    1    2    3    4
	
	do//该循环de效果最为好
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		if (input == 0)
		{
			printf("退出计算器\n");
			break;
		}
		else if (input >= 1 && input <= 4)
		{
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			int ret = pfArr[input](x, y);//调用函数指针数组,pfArr[input]就表示指向的是第什么函数
			printf("%d\n", ret);
		}
		else
		{
			printf("选择错误\n");
		}
	} while (input);//为假退出循环
	return 0;
}

编译就留给你们了!

指向函数指针数组的指针

函数指针数组当然也可以放在一个指针当中了,而这个指针的类型同样与函数指针有关。

假如就拿上面的函数指针数组举例 int (*ptArr[4])(int ,int) 是一个函数指针数组,把它放在一个指针里,(*p)表示指针,其他部分就照搬函数指针数组的类型就行,即: int (*(*pt)[4])(int ,int)

指向的就是函数指针数组的指针变量 p

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CR0712

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值