原创 一线研发之声: 嵌入式C编程经验 之 函数指针的妙用

2012-1-13 11:32 3575 20 41 分类: 消费电子

/***********************************************************************************

* Filename: 一线研发之声:嵌入式C编程经验 之 函数指针

* Author:SedateFire

* E-mail:SedateFire@126.com

* Version:1.0      

* Modify Date: 2012-01-12

* key: 嵌入式 函数指针 回调函数

* 本文首发: 环球资源-电子工程专辑-博客: 静心斋

***********************************************************************************/

        今天讨论什么呢,就讨论函数指针吧

 

        指针,在C语言中,是一个神圣的存在,可远观不可亵玩焉。函数指针,则是指针里面更让人敬畏的存在。

 

         如果你是一个单片机工作者,那么我猜测你八成忘记了函数指针如何定义,我几乎可以想象出你苦苦思索的神态了。

 

        如果你是一个linux底层驱动工作者,那么显然你要感叹造物住的神奇,函数指针竟是如此的遍地开花。尤其是linux 2.6以后的内核版本,你几乎要被指针晃花眼睛了,没有2年工作经验你都很难找到函数的原型定义在哪里。linux内核是一个高度抽象的世界,它把所有外设都视为文件,这一切,函数指针功不可没。

 

        前者太遥远,因为单片机基本上无法应用函数指针。比如Keil C51,函数指针是非常危险的,因为编译器不知道你这个指针要指向那个函数,也就无法分析分配每个局部变量。额...那个静态编译懂吗?用一句形象的话为君解惑,对于静态编译,每个变量(含局部)它的地址都是恒定不变的,但不是唯一的哦C51的栈,只用来存储函数返回地址。当然,特殊的递归编译不在讨论范围之内。所以,单片机程序和函数指针基本绝缘。只有一个途径可以用函数指针,那就是在编译阶段就告诉编译器这个函数指针的对象,且那个函数必须是有定义的,存在的。

 

static const void (*function_pointer)(void) = function_exist;

 

       如果你的单片机程序中,有一个很大的很有规律的类似switch的写法,那么可以改写成静态函数指针数组,用查表方式,无论是可阅读性,还是程序效率,都颇有可道之处。如果不告诉编译器函数指针的对象,那你就完蛋了,程序也许能跑,但bug是莫名其妙的,没有任何逻辑的。如果你说那样干没有问题,那我也不争辩,只盼你能买几张彩票送我。

 

       linux当中的函数指针,那是锣鼓喧天鞭炮齐鸣红旗招展人山人海啊~~。基本上只要是结构体,里面都必有一个函数指针,而且是一层嵌套一层地层层抽象上去,还有一堆令人头皮发麻的void *无类型指针,指针和变量齐飞,代码共数据一色。所以,高薪不是没有依据的。随着android的迅猛发展,大家接触linux内核的机会也会越来越多。

 

       当然多数人没那么好运的,我们说点实际点的,M0/M3平台。这个平台是很适用函数指针的,因为它是压栈式的编译方式。它最广泛的应用是回调函数,就我个人体会来讲,回调函数主要是为了分层清晰和模块化而存在的。我底层想传递消息给顶层,但又不好直接调用顶层函数,于是就用函数指针这种暗度陈仓的方式。有人说,直接调用不就得了,搞什么虚文。问题是顶层随时可能换,函数名也会变,到时候移植起来发现,顶层和底层盘根错节,相互依赖,那是很痛苦的。顶层对底层说,小兄弟,这个事情你先做,有什么情况你就打电话给我,剩下的我来处理。底层含着眼泪对顶层说,哥,你别说了,你还是先把电话号码给我吧,您干嘛老换号码啊。这个记录电话的媒介,就是回调函数指针。

 

        回调之妙,食髓知味。

 

夜了,闪人先,期待本文1.1版吧,呵呵

 

哎,自己回头看了一遍,内容冗余,表达转折突兀,不够圆润,容我再细细梳理一翻...

 

文章评论21条评论)

登录后参与讨论

用户1327925 2012-5-15 09:58

期待新的文章出来

用户1549192 2012-2-2 08:36

有点风趣诙谐的味道,期待你哟!

用户1421223 2012-1-29 16:16

博主能否详细描述一下回调函数的用法和注意事项,新人求指导

xucun915_925777961 2012-1-29 09:11

希望深入讨论,谢谢!

用户1185343 2012-1-19 10:50

函数指针,优点在于可随意更新的输入参数的处理,缺点也正式由这种随意性带来很多不可预知性,任何BUG将会导致极难查找和定位。所以函数指针一般使用于驱动层,可以再由上一层应用来进行封装(较复杂,不建议应用层直接使用),编写这类函数,一般让有经验的人来做(至少是设计),以保证可靠性和稳定性。

用户1602177 2012-1-19 09:05

压力是动力之源啊~

用户1639872 2012-1-19 00:05

鄙人表示鸭梨很大...

用户1406868 2012-1-17 20:33

下次希望能够看到有实质性的总结,不然这种文章意义不大。

用户1627741 2012-1-17 18:27

看了,谢谢。辛苦了

用户1167151 2012-1-17 03:57

楼主应该就Keil C的静态编译专门另写一篇文章。
相关推荐阅读
用户1639872 2014-03-16 12:07
营销自己,实名还是“艺名”好?
积累了一些技术心得,想在网上发点文章博点人气,本着先有名后有利的想法。多数人都是用个“艺名”,用马甲在混。问题在于:马甲这个东西,优点就是好记,而且有一种神秘感,也许自己就是个屌丝,但文章过硬,也...
用户1639872 2014-03-11 23:55
当心中有了牵挂
       上个周末,回老家看2周多的女儿。离别的时候,我不敢扭头就上了车,眼泪就不可遏地直流下来...         以前看宝宝时,离开时只要说句bye,她就呵呵地和你bye,甚至头也不...
用户1639872 2014-01-19 01:29
不知幸亦或不幸,路在何方?
晚上公司尾牙,鉴于往年素餐尾牙吃不饱的经验。部门内部几天前就发起了一场尾牙结束后的k歌聚会。当时没有报名,感觉k歌确实没什么吸引我的。尾牙结束回家的路上,搭乘同事的车,耐不住满车同事的煽动,想想还...
用户1639872 2013-12-25 00:27
一线研发之声 之 完美主义者的程序员特征 <二>
3.空格、换行、常量替换、{}保护、还有效率。 if((long_state_var==1)||(long_state_var==2)||((ch>0x2F)&...
用户1639872 2013-12-24 10:46
一线研发之声 之 完美主义者的程序员特征 <一>
    观文识人,代码无疑是了解一个程序员的最佳途径。     且不论算法思路,单就代码的界面风格,便可知一二。     1. 追求精美的对齐。 尽可能精确到每一个"断点",是他的...
用户1639872 2013-12-23 16:23
一线研发之声 之 C代码注释引发的“血案” (二)
上接:一线研发之声 之 C代码注释引发的“血案 (一)       我开始思考,还有什么强劲有力的理由,来支持我恪守的真理:c语言代码注释必须使用/**/. 有的!      倘若...
我要评论
21
20
关闭 站长推荐上一条 /2 下一条