C语言大世界—————09指针类型之函数指针+函数别名 福利篇

来源:互联网 发布:美国网站域名后缀 编辑:程序博客网 时间:2024/05/16 07:08

函数指针 完整篇!  看了之后将扫除一切障碍!用最简介的词汇 用最幽默的方式给你讲解函数指针 不容错过啊

假如你喜欢我的文章 请关注我 假如我写的不好 请给我指正。本人努力去考虑很多细节,但毕竟还有疏漏的地方 还望见谅!


/******************************************************************@brief:检讨下 前面几篇博文质量不是很高 ,不忍直视... 不过内容改讲的都讲了,代码也都能执行,我反复看了几遍,感觉自己废话连篇,点子是讲到了,可让人看着心烦。作为一个工科男,毕竟文笔三流。今天主要探讨上次遗留的问题,由于出差几天以及项目加急,一直没更新,另外点击量也不高,动力不足了。尽管如此,我觉得坚持就是胜利,一句话开搞! ******************************************************************/#include "stdio.h"typedef void(*ptr_to_func)(int);//不会报错哦 说明正确 int main(){#if 0例子是编程专家例子,只要你看过先前我的文章,理解起来没有问题。char * const *(*next)(); 在解释之前,来个口诀,千万不要背...看完之后咱按照例子往死里扒。 1.抓关键   > 找到next,凡事要抓关键、抓重点。这里就是'next'。也叫标识符! 2.右盼   > 右盼两个东西,首先考虑方括号('[]'),其次是左括号('(',注意  是左括号哦,假如有,再找到对应的右括号)。方括号表示一个数组,    例如a[];左括号嘛,像'a()',函数的调用,写的复杂点就是'a(para1,para2)',这个函数是有参数传入的。  3.四次'左看'而结合  前有大禹三过家门而不入,后又四次'左看'来结合,结合之后可以当做  一个'新的对象',一个'新的标识符',用引号只是假象罢了。方便说明   > 1.左看左括号('('),假如有,找到对应的右括号,开心返回第二步右盼从上往下执行   > 2.左看符号const,有就结合。 继续执行下一步 找volatile   > 3.左看符号volatile,有就结合。 继续执行下一步 找 '*'   > 4.左看符号'*',有就结合。 '*'既是一个开始 又是一个结束。她将再次回到四次左看  从上至下执行,既从找左括号开始.假如一轮左看结束没找到东西 不好意思 结束了!进入下面的善始善终。  4.做事要善始善终  > 剩下的符号只不过是一个声明的基本类型。一并收留吧,I know you    are a good person!....(别想歪) 总结:以上是一个完整的分析流程,很是简单。下面给出几个例子来:example01:char * const *(*next)(); example02:void (*signal(int sig,void(*func)(int)))(int);希望第二个例子没有把你吓到,假如的讲解让你还是无法理解,请联系我!   #endif#if 0example01:char * const *(*next)(); 1.抓关键 抓重点  > next 这个标识符太好找了2.右盼  > 两个东西('[]'与'(',关于符号'[]'我觉得大家都不会搞错,就怕'('    会让某些同志看错,首先是找左括号,然后找对应的右括号结合,其次强调我们的左顾右盼都是相邻的,假如你要说"(*next)()",直接从next 与后面()结合,先说*不答应,右括号')'也不答应啊)。回归正题,很遗憾,右盼啥都没盼到.跳过吧3.四次左看  > 1.左括号'('木有, const 没有,volatile 没有,'*'有!    结合之后是------> *next  这是一个指针....啥类型还不知道!  现在要进行哪一步还记得吗?应该是回到四次左看最开始!老老实实  从左括号开始找起'('   假如不记得在回上文看看!5.四次左看  > 左括号'('有木有!结合之后是----->(*next)  next 是一个指针..   现在应该进行哪一步?要知道'('与 const,volatile,*这一类与众不同,它    返回层次高,回到右盼,而后面3个小伙子是返回四次左看最开始,又从左括号找起6.右盼  > 木有[],但是有左括号啊 然后一路追踪到对应的右括号,结合之后是这样的  ----->(*next)(),    这个有点像函数了,看过前文的同志,应该知道啦!next 指向什么不言而喻。指向函数的指针。有点眉目了!函数返回什么貌似没说! 7.右盼执行完毕又到四次左看  > 找左括号没有,找const没有,找volatile没有,'*'有!    结合之后是这样的 ------->   *(*next)() 这个.... 别慌!镇定!看上面,我们还不知道这个函数返回什么呢? 没错!*就是返回的东西!是一个指针。举个例子int* add();这个函数是返回一个指向int 类型的指针!嗯...原来如此。上面那东西看似吓人,实则简单。最后我们是这么理解:next 首先是一个函数指针,作为一个函数,就算没有返回值,起码写个void。而我们这里是返回一个指针。(*next)你可以当做add 函数名.貌似还不知道这个返回指针到底指向什么.....好了,形势一片大好,现在回到哪一步?YES !是返回四次左看,然后从上到下执行。 8 四次左看  > 左括号木有 找const ,有了! 刚说函数返回一个指针,指针指向什么类型  却不知道.这里不就有点眉目了吗? const 是一个"只读"形容词,和*靠那么近。 那么这个指针就是...停 stop! 我知道你要说什么。const 可不是形容指针(函数返回的那个指针)'*'表示什么? 表示指针指向啥啥东西,而const 就是来形容这个啥啥啥东西是只读的!不过这个指针返回什么类型还是不知道... 唯一确定的是那东西是只读。 现在该怎么办? 执行下去呗查找volatile没有 找'*'有 结合起来是这样的-----> * const *(*next)()哦?又指向了一个'*' ,尼玛 牛逼。函数返回一个指针A,而这个指针A 竟然又指向另外一个指针B 。注意这个指针B 是只读的!现在貌似又要返回四次左看。9 四次左看  > 是时候结束了 没有了const 没有了volatile 没有了 *,我们要最后收留了目前是这样的 * const *(*next)();next 是一个函数指针 该函数返回一个指针A, 指针A 指向另外一个只读指针B 那么这个只读指针B 又指向什么东东呢。请看下文 10 结尾   > 还剩 char 不言而喻  只读指针B 指向一个char 类型。终于走到了尽头。  next 是一个函数指针 该函数返回一个指针A, 指针A 指向另外一个只读指针B  这个只读指针B指向了 char 类型数据 !   #endif #if 0example02:例子如下: void (*signal(int sig,void(*func)(int)))(int);该例子不罗嗦,正经分析! 1.抓关键> 这里抓关键是抓哪个?signal? sig? func? 其实明眼人一看就知道 必须是  signal   至于sig func 其实只不过是函数传入的参数名罢了,这都是后话,  先按下不表(卖个关子)。   2.右盼> 没有[] 没有右括号'(',有!集合直到找到对应的右括号,别告诉我你找不到.....  signal(int sig,void(*func)(int))//最后结果是这样的   signal()//忽略里面东东  signal //嗯 是一个函数   那么int sig ,void(*func)(int) 就是传入的参数  用我的方法分析下,传入的是啥参数,这里就不展开讨论了   除去我们已经挖掘的 还剩下 void (* )(int)   现在我们进行下一步 左看左括号3.左看左括号> 没有 那么只能进行下一步了4.左看符号> const 没有 volatile 没有 这两家伙千年不在 -.- 。'*'有 结合之后是  *   signal(),我很怕你认为这是一个函数指针,所以我远远的将他分开  刚才上文已经拍板了定论了,signal 是一个函数。至于函数指针应该是  这样申明(*func)()!!! 那么这里的 * signal() 中的'*'只能是一种可能  了,就是函数返回类型是一个指针!啦啦啦 好开心 明白了 最后的结论是  signal 是一个函数 传入参数为 int sig 和 void(*func)(int) 返回一个  指针 至于这个指针指向什么 我还不知道!   继续往下走 回到左看左括号 希望你还没晕 记住符号'*'要返回就返回左看  左括号那边 。现在还剩 void ()(int) 5. 左看左括号 >  有不是吗, 将我们现有的部分结合左括号 直至对应的右括号 现在应该是这样的  (我们的部分)  没区别哦! 接下来要返回的是右顾了!6.右顾> 有左括号 结合 直至对应右括号 轻车熟路!现在应该是这样的  (我们的部分)(int)  如果我们写成 (我们的部分)() 是不是很容易就能明白  "我们的部分"在具体就是 *signal(参数省略)  代入就是  (*signal())(int)  兄弟们 出来了 刚才我说了 signal 是一个函数 返回类型  是一个指针,至于它指向什么我还不知道。但是这里我们不就知道了吗,她居然  指向一个函数!传入参数是int 。激动啊 那么问题又来了 返回什么类型  别急 不是还没完吗?我们进行到右顾之后 要往下走 但是剩下只有一个void  貌似不是左括号,不是const 不是 volatile 不是 '*' 只能善始善终啦7.最后的焰火那就是void  哎!这个返回的函数指针竟然指向一个输入参数int 返回 void 的一个函数。你以为这就结束了吗??对于void (*signal(int sig,void(*func)(int)))(int) 我们轻轻松松搞定 但是一眼看去还是颇为复杂,那么如何来简化? 还记得signal 作为一个函数 传入的第二个参数是什么?即 void(*func)(int)那么作为signal 函数的返回类型是什么呢?即一个指向void (*)(int) 的函数指针 两者很像不是吗? 错 是一样 只不过后者省略了func 。还记得typedef 吗我想用他创造一个新的类型 也就是 void (*)(int) 那么如何来定义呢。其实你翻翻我的最开始几篇文章就能知道,我会告诉你我是有预谋的吗是这样用的typedef void(*ptr_to_func)(int); 别名在哪里? ptr_to_func!这就是我们构造的类型啦现在这么写 ptr_to_func signal(int sig,ptr_to_func func);signal 是一个函数 接受两个参数 一个是sig 一个是func 特别申明类型是 ptr_to_func函数返回类型是ptr_to_func谢谢观看! #endif printf("hello This is a special world of C language!!\n"); return 0;} /*番外篇:摘自百度: 标识符使用来标识源程序中的某个对象的名字的,这些对象可以是语句、数据类型、函数、变量、常量、数组等。C语言规定:一个标识符由字母、数字和下划线组成,第一个字符必须是字母或下划线,通常以下划线开头的标识符是编译系统专用的,所以在编写C语言程序时,最好不要使用以下划线开头的标识符。但是下划线可以用在第一个字符以后的任何位置。基本原则是:变量名=属性+类型+对象描述,其中每一对象的名称都要求有明确含义,可以取对象名字全称或名字的一部分。命名要基于容易记忆容易理解的原则。保证名字的连贯性是非常重要的。 */</span>



1 0