指针函数、函数指针与回调函数

前言

初学者碰到指针函数和函数指针往往会混淆概念,区分不清。其实区分这两个概念看的就是后面两个字,前面的两个字就是用来修饰的形容词。**我们需要通过后面两个字,区分它们究竟是指针还是函数。**下面我们将通过C代码来具体分析二者的区别,并进一步引出回调函数的概念。


指针函数

定义与声明格式

指针函数:看到最后两个字,顾名思义就是函数。它的本质是一种函数,返回类型是某一类型的指针。
声明形式:类型标识符函数名(函数参数1,函数参数2,…);
以下几种方法都是正确的:
(本人比较喜欢第一种方法,便于提醒自己返回值是int类型)


int* fun(int a, int b); //该函数是一个有两个int类型的形参,返回值是int类型的指针,是一个地址;
并且该函数的返回值一定要用一个相同类型的指针来接收。

代码用例

在这里插入图片描述

运行结果

在这里插入图片描述
在函数fun()中malloc的地址空间地址为:0x1360150
在调用函数时,返回的地址空间也是:0x1360150
在这里一定要注意一个问题,就是不能返回栈空间的变量的地址,栈空间中的变量的生存周期是函数调用开始到函数返回。如果返回的地址是栈中的 变量地址,那么在函数结束时,该地址已经不是合法空间了。程序可能会正常运行,但是此时没有其他变量去改变该地址空间,如果该地址空间被改变,那么将发生错误。
一定要返回的是合法空间的地址,在函数中malloc的地址空间,要注意使用free()函数释放哦,不然很容易造成内存泄漏!


函数指针

定义与声明格式

函数名字就是函数的入口地址,这时候我们可以定义一个指针指向这个函数,这个指针就是函数指针。
函数指针:**其本质是一个指针,该指针指向一个函数,**不是普通的数据类型或者某一对象。
声明格式:类型标识符(*指针变量名)(参数1, 参数2,…);
在这里插入图片描述
int (fun)(int a, int b); //该指针是一个指向参数为int,int类型,返回值为int数据类型的变量的一个函数
int
(*fun)(int a, intb); //当然函数的返回类型也可以是指针

代码用例

在这里插入图片描述

运行结果

在这里插入图片描述
这里可以看到主函数中的ptr就是一个函数指针,指向一个形参为int,int,返回值为int类型的函数,通过ptr=add;和ptr=mul;可以执行形参和返回值相同,但功能不同的函数。
这里可能会有一个疑问,这里我直接调用add和mul不好吗?其实是一样的,这里我们就会引出callback函数,回调函数就是函数指针的进阶使用。


回调函数

什么是callback函数呢

回调函数是指 使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,就是由别人的函数运行期间来回调你实现的函数。
在这里插入图片描述
我们可以用一个生活化的例子说明一下什么是回调函数:

你到一个商店去购买东西,你要购买的东西刚好没有货,于是你在店员那里留下了你的电话号码,过了几天店里有货了,店员就打了你的电话号码,然后你接到电话后就去店里取了货。

在这个例子里,你的电话号码就叫回调函数,你把电话号码留给店员就叫登记回调函数,店里到货了叫做触发回调事件,店员给你打电话叫做调用回调函数,你去店里取货叫做响应回调事件

函数指针实现回调函数

回调函数就是把某一个函数作为参数传递到另一个函数中,在另一个函数中则会调用该函数(本案例中的add()函数和mul()函数就是回调函数)
回调函数是由函数指针来接收的;(这里在注释中使用typedef来巧妙地定义)
在这里插入图片描述

运行结果

在这里插入图片描述


注册函数的实现

一般来说,会把回调函数通过注册函数,保存在注册函数所在类的成员变量中,在适当的时候,通过该成员变量去访问注册过的回调函数。

注册函数在注册之后不会立刻发生调用,只有条件满足的时候才会调用函数。
signal()函数就是注册函数,我们先看一下man手册中对signal函数原型的介绍
在这里插入图片描述
signal()函数的第一个参数是一个int 类型的变量, 第二个参数是一个参数为int类型, 返回为void 的一个函数指针, 它的返回值是一个注册成功的函数类型;
即: void (*ptr)(int) signal(int signum, void (*ptr)(int) ptr);
这样一个函数看起来非常庞大, 返回值是一个函数指针, 参数一个是int, 一个是函数指针;
这个时候我们可以巧妙的使用typedef;
在这里插入图片描述
下面的用例是使用一个函数指针去实现一个signal()
在这里插入图片描述

运行结果

在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值