C语言函数指针转发表小实例

1 篇文章 0 订阅
1 篇文章 0 订阅

一、代码部分

#include<stdio.h>

/*
int add(int ,int);
int sub(int ,int);
int mul(int ,int);
int dil(int ,int);
*/
//加减乘除的具体实现
int add(int first,int second){
	return first + second;
}
int sub(int first,int second){
	return first - second;
}
int mul(int first,int second){
	return first * second;
}

int dil(int first,int second){
	if(second == 0){
		printf("ERROR!!\n");
		return 0;
	}
	return first / second;
}

int main(int arc,char **argv){ 
	int first = 0;
	int second = 0;
	char opr = 0;
	//'+','-','*','/'对应的ASC2码分别是43 45 42 47
	int (*op[])(int ,int) = {&mul,&add,NULL,&sub,NULL,&dil};
		//这里需要解释下  int (*op[])(int,int) 
		//op是指向 需要两个int型参数的返回值是int类型的函数 的指针 的数组
	printf("please input(num operate num)>>>");

	scanf("%d %c %d",&first,&opr,&second);//输入格式是 “第一个整数 操作符 第二个整数” 中间有空格
					//没做数组越界判断,所以输错格式程序会出错
	printf("result>>>%d\n",op[opr-42](first,second));

	return 0;
}

二、函数指针解释

函数指针就是指向函数的指针,简答的声明方式:type (*function)(type parameter)

要理解类似的指针函数等混合在一起的声明并不困难,只要把握了 操作符优先级 和 操作符结合性,然后从里向外分析就好,

例如:一个最基本的例子int *fun(int); 

首先,我们要高清楚我们要做的是分析工作是什么:分析fun是什么,注意是fun是什么,二不是fun()是什么,这是有差别的;

其次,从里向外看,最里层是fun,我们探求的目标,然后外面一层是()和*,显然()结合性是最高的,所以我们得到了一个fun(int),它是什么呢?它就是它左边剩下的int*,他们是等价的(或者应该说fun()将会返回一个int类型指针);

然后,我们在一fun(int)为基础再往外层看,得到*fun(int),它就是左边的int;

所以从int *fun(int)我们可以分析出,fun是需要一个int型参数,它的返回值是一个指向int型的指针

 

这时在看int (*fun)(int)就很明了了

fun它的左边是*,所以它是一个指针

(*fun)它右边(int)优先级最高,所以(*fun)是一个函数,它需要一个int型参数

(*fun)(int)它左边是一个int,所以(*fun)(int)是一个int型

所以fun就是指向返回值是int 需要一个int型参数的函数 的指针。

数组指针,指针数组什么的其实也是一个道理,例如:

int* arr[],因为[]优先级比*高,所以arr是一个指针数组(一个装了很多int型指针的数组)

再看int(*arr)[],arr就是指向int型数组的指针了

 

最麻烦的应该就是数组指针函数混合起来了,例如上面代码中的int (*op[])(int ,int)

op旁边[]优先级最高,所以op是一个数组;

op[]在旁边是*,所以op[]是一个指针;

*op[]旁边(int,int)结合型最高,所以(*op[])是一个函数;

最后剩下的是最左边的int,即(*op[])(int ,int)返回值为int;

所以op是什么就不说了,你懂得。

 

说到这里上面在看上面的代码就很简单了,其实就是构造了一个函数指针数组,然后在使用不同的操作时调用用相应的函数而已。

其实,MFC的消息转发机制也是使用了这种思想

下面简单看一个一个简单的MFC单文档工程的消息转发表是如何建立的(我建立的工程命为test):

CMFCtestApp头文件中有一行宏DECLARE_MESSAGE_MAP(),它就是消息转发表的声明,右键跳至定义:

#define DECLARE_MESSAGE_MAP() \
private: \
	static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
	static AFX_DATA const AFX_MSGMAP messageMap; \
	virtual const AFX_MSGMAP* GetMessageMap() const; \


可以看到它声明了一个AFX_MSGMAP_ENTRY 数组_messageEntries,其实这就是那个转发表,AFX_MSGMAP_ENTRY是一个结构体:

struct AFX_MSGMAP_ENTRY
{
	UINT nMessage;   // windows message
	UINT nCode;      // control code or WM_NOTIFY code
	UINT nID;        // control ID (or 0 for windows messages)
	UINT nLastID;    // used for entries specifying a range of control id's
	UINT nSig;       // signature type (action) or pointer to message #
	AFX_PMSG pfn;    // routine to call (or special value)
};


可以看到它包含了一些消息类型nMessage、ID等数据,最后一行就是nMessage对应消息的处理函数,MFC就是通过类中的这个消息映射表实现的消息转发,其实也就是个函数指针的使用。

 

weibo.com/TMDJoJo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值