00:00
各位同学,我们来看一下函数指针,那首先我们现在理解理解一下什么叫做函数指针哈,函数指针呢,简单的讲就是指向函数的指针,就说我们前面不是学过。呃,指向int类型的指针,我们要我们称之为int类型指针,是不是我们也有指针指向float double。或者是指向一个char。那么我们在这个C语言里面呢,它也支持一种指针,这个指针呢,可以直接指向一个函数,怎么理解这句话呢?看下面。一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数该函数这个,这多了一个一该函数所在内存区域的首例值,这跟数组名很相似。
01:00
也就是说,你你可以理解成我们可以把一个函数,我们可以把一个函数名。把这个函数名当作是一个函数的首地址,然后呢,赋给函数指针,就这样理解就行。把函数的这个首地址或者称之为入口地址赋给一个指针变量,使指针变量指向函数所在的内存区域,然后通过这个指针变量呢就可以找到并调用该函数。这样的指针我们称之为函数指针。对这样的指针,我们称之为函数指针。那么我们这样子举个例子来帮助同学们理解。比如说。我们看一个函数指针的定义,这个就是一个函数指针的定义,那么这里面有几个部分构成呢?主要有四个部分构成,我们看第一个return type。这个return type呢,就是为这个函数返回值的类型。就是你这个函数啊,就是你你你原先这个函数,比如说你有一个F这个函数,这个函数它返回的类型就要写到这个位置。
02:09
Point name呢,就是我们这个指针的名称,就是这个函数指针的名,函数指针的一个名字。那么part list呢?就是我们函数的参数列表,就是你这个函数指向的函数的参数列表。第四点,参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称。这我这样讲,可能同学们还是嗯,不太明白老师在说什么,这个你先听着啊,一会儿我们举例子再回头来说,这四点大家就一目了然了,我们再看第五点,注意这个小括号是不能省略的。就这个小括号的优先级呢,高于星号,所以说第一个括号不能省略,就是这个这这个括号不能省略,如果我们把return type星号如果写成了这样一个,把把这个小括号去掉的话,写成这个格式,那么这个就变成函数的原型了,它表示函数的返回子类行为re return行就是一个返回指针的一个函数了,明白了吧,这是两个不同的概念。
03:21
那我这样讲了,同学们肯定还是没有感觉这样子,我们直接举一个例子来给大家演示一下函数指针的使用,我们现在呢,用指针来实现,准确的讲用函数指针,好吧,用函数指针来实现对函数的调用,返回两个整数中的最大值,那么既然你是要整要去创建一个函数值的,那你首先得有个函数,好,我们一步步来看一下,来同学们,我举个例子。我给同学们举例说明,好吧,我给同学们举例说明,那现在呢,我们写个函数指针。那我写哈,Function pointer。
04:04
对,Function pointer。那现在呢,我把他的。名字给他改一下方。得洗澡去了。Function pointer。好在这儿。我们呢,来这样玩一下。首先让我写一个include std。然后呢,我写一个函数,比如说这个函数呢,我已经写好了,就是这样一个函数啊,比如说我这样我这样子直接写就行了,好吧。我这样写,这是不是一个函数啊,同学们看这是不是一个函数,这是说明一下。一这个是max是一个函数,这个max函数它是干什么呢?它接收看啊,它接收两个,哎,它接收。两。他接收两个参数。
05:00
两个类型对返回,返回较大的。较大的这个数是这样子的吧,然后呢,下面我们就可以写一个函数指针来玩一把,那么函数指针咱们怎么玩呢?把这个代码拿过来我用一用哈。首先,同学们跟上老师的思路。同学们看,这边我定义了三个int类型。重点是在这儿。往下看,同学们看说明。注意听哈,我们首先看这一句话。这句话怎么理解呢?这个要这么去理解,就是。嗯,我们我们先一个一个的解释,这是一个下面这个是函数指针,就是对说明函数指针。函数指针。那么函数指针第一个,它的名称是什么呢?这个函数指针的名称名字。
06:00
函数指针的名字是哪个p max?看懂了吗?P max,然后呢,同学们可以看到这个int,注意听啊。这个第一个这个int表示。表示该函数指针。指针指向的函数,指向的函数是什么呢?是这样写是。指向的函数是返回int类型的,这大家能看懂吗?就说我将来这个函数指针会指向一个函数。这个这个函数呢,它返回的类型是int,也就你必须是指向一个返回int类型的函数,理解了,那我们再来看第三点。第三点呢,同学们可以看到下面这有两个这样的形参。表示什么呢?OK,注意听表示,表示该函数指针。
07:01
该函数指针指向的函数函数是什么呢?是接收它的行参啊,指向的函数的形参形式行参式接收接收两个两个int。这个这个接收两个int就可以了,就是它必须是指向这样的一个函数,那么同学们看max是不是满足条件,你看max这个函数呢,它返回值是int,它的行参是接收两个int,因此呢,这样子就是OK的。这样就OK,那这句话如果我们画的再明白一点,说老师你给我能画一个示意图表达一下这个含义吗?也可以,我你可以这样理解,好同学们你可以这样理解。你可以怎样理解呢?呃,我们我们知道大家都大家伙都知道,我们内存里面呢,分了三个区域。一个呢,是我们的这个战区。
08:03
明白这个意思哈,还有一个是我们的堆缺。这是我们的堆,还有一块,是不是还有两块,一个是我们的静态区,或者叫做全局区,是不是还有一块是我们的代码区啊。是不是还有一块代码区,我们现在就单说代码区。那么你可以怎么理解呢?你可以这样理解说,我们这有一个max函数。它呢,放在这个代码区的,这个能理解不放在代码区,放在代码区呢,如果说我在这里有这么一个动作,有这么一句话。在我的站里面呢,我执行了这么一句话。当然这个现在是在主主函数站里面,对不对,我有这么一诶。写错了啊,我有这么一句话。看懂了,那你可以怎样理解呢?你可以这样理解,你你可以这样大家看。
09:03
他呢?它是把这个max的这个首地址给到了p max,也就是说你可以这样简单理解说,有个叫p max的这么一个指针,它呢。他自己当然是有地址的了啊,你可以你可以简单这样理解就行了,好吧,咱们不用画那么复杂了,你你可以认为它直接指向了我们这一个代码区的这么一个,呃,就它p max就指向了我们这个函数。就可以简单这样理解。这可以简简单这样理解,能能明白这个意思吧,好,那么我们这样理解过后,我们怎么去调呢?调用的时候其实很简单,就是星号P,然后这个就是代表调用。这这个地方,这里面这句话说明这个代表的就是调用我们的就是通过函数指针去调用,调用什么呢?调用函数。
10:04
诶,这个星号不能少哈,同学们,你可以简单理解成好像是p max,通过这个星号能够找到我们指向的这个这个函数,你大家还记不记得,我们以前也是这么去玩的,要去找一个东西都是新什么什么,然后找到它对应的这个内容是不是?诶你可以这样去理解,就好像星号p max呢,就取到了我们这个函数的首例值,然后呢,去执行我们这个函数。就这样理解就可以了。这样理解就没有任何问题好吗?好,那这样子的话呢,嗯,这样子的话呢,我们可以来跟大家去来测试一下了。测试一下。大家看,我在这有个函数指针,然后呢,我输两个数X和Y,然后呢,我通过这个函数指针去调用我们的函数这个max。啊max,然后通过这个max呢,我们传了一个X和Y,那么这个XY呢,是我输进去的,然后最后呃,根据实际的情况,返回一个最大值,代码就结束了,好吧,我们来运行一下。
11:12
把前面我们都注销了,跑起来。我们输入两个数,看一下它能否返回最大值。好,这里有个错误,错误的原因是不是因为前面没有注销呢?哦,这边有一个没有注销的。好,我们再来运行一下。我们再来一下运行point函数指针这个案例。好,稍等片刻。那现在呢,我们待会,呃,我们一会就输两个数哈,现在同学们看我输一个十,再输一个80回车,最大值是80,正确的再按一下就退出去了,嗯,就这么去理解,当然有同学说老师我们能不能看到函数指针它本身的地址呢?如果说你这样子去可以试一下,比方说大家看我们这有一个p max。
12:06
对。屁。对吧,我们这样输出一下,看看能否输出一个内容哈。我们这样输出对不对,我们这样输出。好,我们来玩一下。哎,我们来玩一下,看一下这个情况。运行之。运行之。好,我身上输一个十,输一个40。你看是不是也有个地址啊,013C1005,那么当然了,有同学说,老师那这个函数指针它本身有没有地址呢?我们也来输出一下p max本身的地址。哎,本身的地址。我们来也输出一个好不好,那这样子的话呢,要输出它的地址就得用什么呀,用at符号p max。是不是这样子来输啊,好,我们再来玩一把,看看能否输出哈,能否输出来走一个运行。
13:03
好运行,我们仍然输出一个十,再输出一个20,输一个十,输一个20好吧。好的,输一个十,再输一个20回车。好,我们可以看到是不是p max呢,它有一个,呃,里面存了一个地址,然后p max本身的地址是这个两个不一样,对不对,所以说你可以这样去理解,怎样理解呢?你可以认为这边呢,会有一个指针。OK。OK,这有一个指针,嗯,那么那么这个指针我们这样画吧。啊,我们我们这样子画画一个,诶怎么变成这个了。好可以这样子,我们我们插入一个表格。啊,这样子话看得比较清晰。小号线我们指向一个空间,这个空间呢,里面存了一个地址,是指向我们这个,呃,这个函数的首地址的,比如说是0X1122,我打个比方哈啊,就说它它这呢指向了这个地方,就好像我们这个函数呢,它它不是指令吗?指令肯定也有个地址嘛,你可认为函数的就是函数的首地址。
14:14
它函数首地址就是0X1122,能理解了吧,就相当于说我们就指向这个函数的首地址,那么就指这个函数的入口了吗?那么嗯,还有一个呢,就是大家要理解,就是说它本身也有个地址,比如说0X1133。对,也就是说这个,嗯,我们这个函数指针呢,它本身也有个地址啊,就这么一个情况,那当我们要去调用这个函数的时候呢,调用这个函数,我们通要通过这个地址去拿到这个函数,那就应该怎么走了呢?得这样去走,诶这样去走怎么走哈,给大家演示一下,就是星号星号p max。包起来OK,那这样子的话呢,同学们这样子一写呢,里面就传你的值,比如你传个十传个20,那怎么理解呢,就相当于说我们前面这一部分。
15:03
这一部分就取到了我们这个函数,是不是这样就取到,因为你你用这个星号星号PX才能才能去取值嘛,取到了我们这个相当于说找到我们这个函数了,然后呢,再看它传入行参呃时参就可以了,能理解这个意思了吧。好,这是一个很重要的原则,一个规则老师就讲完了好吗?好,那么再多说一句啊,各位同学,我再多说一句,嗯,还有一种形式,就是有些人呢,他喜欢这么去写也是OK的,我再加一句话。第四点对在在定义定义这个函数函数函数指针时,指针指针。指真实也可以,也可以写上,写上什么行参名啊,写上也就是说你这种写法。你这种写法也可以写成这种形式,比如说我这写个A。
16:01
写个B啊也可以,当然你要说老师我写个X和Y可不可以一样的啊,一样的就是有些人呢,他会这么去写,你比如说我这样写也是没有问题的,我写个X,再写个Y,表示什么呢?表示我这个地方就有明确的两个,呃,两个行参也是可以,因为有些人习惯后面带一个名称嘛,但是这个名称,嗯,不一定非得给我们这个马克X的行参名一样,因为行参的名字并不重要,关键是传输的时参才是具体的值,你看这样一写过后呢,仍然没有任何问题啊,各位同学跑起来。哦对,我把这个先推一下好吗?运行啊,这是一个比较重要的概念,来跑起来。那跑起来过后呢,我们来看一看呗,我们来看一下啊好,你看我再输一个十,再输一个89,应该返回来了。好,可以了,这个大家就都明白了吧,都明白了哈,我还把这个撤回去好吗?好,各位同学,那关于我们讲解的函数指针就给大家聊到这里,我把这个东西简单的板述一下,我们讲了哪些内容,函数指针捋捋。
17:08
那么函数指针呢?我们怎么讲的呢?首先我们仍然是先给同学们介绍了一下什么是函数指针,其实函数指针简单的理解一句话就可以说清楚,就是指向函数的指针就是函数针。对吧,我们原先说呃,整形指针,或者说float指针,你指向整数的D,指向整数的那个地址的指针就是整数指针,那么我们指向函数的指针就是函数指针,就这意思,那么这写的很清楚。压这儿啊。把函数的首地址赋给一个指针变量,那么呃,让这个指针变量指向函数所在的内存区域,好,那么这个指针就是函数指针,就这么简单哈,没有什么特别复杂的,它的它的作用和它的这个原理和前面前面学的指针其实大同小异。
18:02
那然后我们这个说完了,是不是就给同学们说了一下,怎么去定义我们函数指针是不是,诶OK,这是函数指针的一个定义。那么这里呢,我总结了五点,明白这个意思吧,五点,那这现在同学们再来看,是不是就看的比较清晰了呀,你看哦,Type是函数返,就是你这个指针指向的这个函数返回的类型。对不对?Point name呢?就是我们这个指针名part list就是指向的函数的参数的列表,这样写清楚一点吗?Return type是为这个函这样写哈,就函数函数指针指向的函数返回的类型是不是更清晰一点?Pointer name呢,就是指针名字函数指针名。函数指针里,而para list呢,就是就为什么呢?就是函数指针指向的函数的参数列表是不是更清晰了?好还有一点参参数列表中可以把这个呃参数名带上,也可以不写好,还还有这个小括号不能丢掉。
19:14
小括号是不能丢的,小括号丢了就麻烦了哈,那小括号丢了就代表你返回的是你写了一个返回指针的函数了,那意思就完全不一样了。好的,这个讲完是不是老师就讲了一个应用案例,而且呢,做了一些底层的分析,好这个案例我给大家拿过来好吧,那么案例呢,实际上是在这。我们这儿有相应的注释。还有一个对它的分析的内存图。代码给各位朋友板书到这边来,这是我们的案例,好,再写一个。就是案例,就是我们叫函数。函数指针的内存布局。是不是啊,同学们,内存布局好,那现在呢,我把这个拿过来好吧。
20:03
记住这个大概就OK了。好,各位朋友,我把它呢给大家放到这里来。好,各位同学,嗯,关于函数指针呢,我们就给大家讲解到这里,大家消化一下,然后接着我们再讲新的内容。好,这一讲我就聊到这里。
我来说两句