函数指针&&函数指针数组

概述:

       函数指针和函数指针数组是C 语言中相对比较绕的概念,对于初学者来说很不友好。在我刚刚接触C语言中这两个概念的时候也是一头雾水,萌生退意。尤其是当指针数组,数组指针,函数指针,函数指针数组这些东西结合到一块的时候。我们更要知难而进,逐步拆分,细细品味。

函数指针:

      从名字上理解,就是指向函数的指针,本质上是一个指针,存放函数的地址

其形式如下所示:

int add(int x, int y)
{
	return x + y;
}
int main()
{
	int (*pf)(int, int) = &add;
	//此时的pf就是一个函数指针变量
	return 0;
}

与数组指针相类似,(*pf)说明他是一个指针,往后走看见(int,int)说明他指向一个函数,函数的两个参数为int int,返回值也为int。

对于初始化这块:函数名就是他的地址。

&add   ==   add

所以我们可以写为:

int (*pf)(int, int) = add;

 我们应该如何对函数指针进行调用呢,以下代码就能很好的进行说明。

 因为pf里面存放的是函数的地址,对pf进行解引用就找到了函数的地址,参数部分我们把3和5传进 去,返回值用ret进行保存。

int add(int x, int y)
{
	return x + y;
}
int main()
{
	int (*pf)(int, int) = add;
	int ret = (*pf)(3, 4);
	printf("%d\n", ret);
	return 0;
}

结合以上的信息我们就可以分析如下两段代码:

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

 这段代码的作用其实是调用0地址处的函数,我们如下进行初步分析:

1.void (*)()  : 函数指针类型。

2.(void(*)())0  :把0强制类型转换为一个函数地址。

3.*(void(*)())0  :对0地址处进行解引用。

4.(*(void(*)())0)()  :调用0地址处的函数。

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

 对这段代码我们也可以进行如下分析:

1.signal首先和()结合,说明signal是一个函数名

2.signal函数第一个参数为int,第二个参数为函数指针类型(参数为int,返回类型为void的函数)

3.剩下的 void(*    )(int) 便是signal的返回类型,类型为一个函数指针(参数为int ,返回类型为void)。

以上表达式出自《c和陷阱》这本书中,我们在刚刚接触这类表达式第一感觉就是头大懵逼,但是如果我们连这个的代码都能读懂,都其他的代码应该不会有太大的问题。

函数指针数组:存放函数指针的数组。

对于函数指针数组的应用与实现,以下这个例子就可以体现。

比如我们要写一个计算器,实现加减乘除的运算,一般的方式来写我们可以写为这样:

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.退出        ****\n");
	printf("****************************\n");
}
int main()
{
	int input = 0;
	int ret = 0;
	int x = 0;
	int y = 0;
	do
	{
		menu();
		printf("请选择\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			ret=add(x, y);
			break;
		case 2:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			ret=sub(x, y);
			break;
		case 3:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			ret=mul(x, y);
			break;
		case 4:
			printf("请输入两个操作数:\n");
			scanf("%d %d", &x, &y);
			ret=div(x, y);
			break;
		case 0:
			printf("退出程序");
			break;
		default:
			printf("xuanzecuowu");
			break;
		}
		printf("%d\n", ret);
	} while (input);
	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.退出        ****\n");
	printf("****************************\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();
		//pfarr就是函数指针数组
		int (*pfarr[5])(int, int) = { NULL,add,sub,mul,div };
		int x = 0;
		int y = 0;
		int ret = 0;
		printf("请选择: \n");
		scanf("%d", &input);
		printf("请输入要操作的数字: \n");
		scanf("%d %d", &x, &y);
		ret=(pfarr[input])(x, y);
		printf("ret = %d\n", ret);
	} while (input);
}

 

这样看起来我们的代码就简短方便的多了,这其实就是函数指针数组的一个应用,但这样写的前提的add sub mul div他们的参数和返回类型都相同。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

浪花猪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值