c语言函数指针类型有什么用,C语言陷阱与技巧第26节,一文弄懂“函数指针数组”,为什么不直接调用函数,而是通过指针调用?它有何意义?...

通过前面两节的讨论,相信读者已经发现C语言中函数指针的灵活与强大了。毫不夸张的说,C语言的指针语法,有时甚至让C语言看起来像具备了“新特性”似的。

6180642cd4cd2b35a4a2e533e25e7e06.png

将指针当作一种普通数据类型

不过C语言指针的灵活与强大,也导致很多初学者认为指针是一个很难的概念,因此在遇到指针时,常常会觉得“紧张”。例如下面这个例子:

int fun(int a){ a = 3;}int val = 1;fun(val);printf("val = %d\n", val);即使是初学者,只要了解了函数形参和实参的关系,也知道上面这段C语言代码编译后会输出 val = 1。但是如果将C语言代码做适当修改:

int fun(int *a){ a = (int*)3;}int *val = (int*)1;fun(val);printf("val = %p\n", val);

550404a42cde046b4d605633fbc06b62.png

这段C语言代码编译后,会输出什么呢?可能一些初学者会认为输出 val=0x3,但是将这段代码实际编译运行,得到的输出却是:

# gcc t.c# ./a.out val = 0x1怎么回事呢?原因当然是简单的,这个问题仍然可以用函数形参和实参的关系解释,很基础。但是有些初学者还会迷惑,“这可是指针!”其实,这就是将C语言中的指针“特殊化”了。

在分析指针问题时,一个小技巧就是将指针当作C语言中的“普通数据类型”,例如可以将 int* 变量看作是“int指针型”变量。现在改写上面的C语言代码:

typedefint* IPTR;int fun(IPTR a){ a = (IPTR)3;}IPTR val = (IPTR)1;fun(val);printf("val = %p\n", val);这里使用 IPTR 表示 int* 类型,一切看起来就很容易理解了。

“函数指针类型”

既然把C语言中的指针看作是一种数据类型,那么函数指针也就容易理解了,也不过是一种像 char 、int 一样的数据类型而已。char 、int 作为C语言中的基础数据类型,是允许用其定义数组的,那函数指针这种“数据类型”也可以定义数组吗?答案是肯定的,请看:

typedefint (*funs[8])(int *data);上面这行C语言代码就定义了一个函数指针数组 funs,funs 可以管理 8 个函数指针。有时候为了便于理解,上述代码常常会拆解成下面两行:

typedefint (*FPTR)(int *data);FPTR funs[8];funs 的各个元素可以执行原型为 int f(int *p); 的函数,例如:

funs[0] = fun;funs[3] = fun;使用 funs 实现函数调用也很简单:

funs[0](val);funs[3](val);函数指针数组的意义

相信读者已经了解函数指针数组的定义和使用了,那它有什么意义呢?实际嵌入式C语言项目开发中常会遇到这样的需求:服务端采集到数据后,需要将其分别发送给模块1、模块2、…、模块 n,但是各个模块使用的协议不一致,因此这里假设每一个模块都定义了一个函数用于传输数据:

void m1Send(void *data){// 模块1 发送函数}void m2Send(void *data){// 模块2 发送函数}...void mnSend(void *data){// 模块n 发送函数}这些发送函数根据各自的协议自定义逻辑,但是接口却是一致的,如果服务端需要分发数据,则需要:

m1Send(data);m2Send(data);...mnSend(data);如果有若干组数据需要分发,那么上面这样的C语言代码需要重复写若干次,太繁琐了,而且重复的代码不利于后期维护。这种情况下,使用函数指针数组就非常方便了:

void (*mxSend[N])(void *data);void init(){ mxSend[0] = m1Send; ... mxSend[N-1] = mnSend;}只需调用 init() 函数将各个模块的数据分发函数注册到 mxSend 数组,之后使用 mxSend 就很方便了,请看下面的C语言代码:

int i;for(i=0; i

小结

经过本节的讨论,相信读者能够发现C语言中的指针也不过如此,在实际使用中,只需将其当作普通的数据类型就可以了。这样一来,函数指针数组也就不难理解了,合理的使用它,可以写出更加紧凑的C语言代码。本节最后还举了一个数据分发的实例用于说明C语言函数指针数组的方便,当然了,函数指针的用途远不止于此。

51261def1ab0d226630f9b44c59bcf59.png

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

举报/反馈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值