00:00
各位,我们再来给大家讲一下传递指针,或者说叫传递地指给函数,其实传递指针或者说传递地址这个知识点我们在前面已经讲过了。其实是已经讲过的,大家还记不记得我们在前面讲这个指针的时候,我们说通过指针交换两个整数的值,还记得吧?其实内容已经讲过把这个指针或者说地址传给这个函数了,我们这边再把它梳理一下,当函数的形参类型是指针类型时,是指使用该函数时需要传递指针及地址。对,或者说你直接把一个数组传给这个行参也是可以的,因为数组默认是指针传递,还记得吧?好,我们现在呢,直接给大家看几个案例,梳理一下就可以了,看这个案例,我想请同学们思考一下,这个应该输出什么结果,我们一起看一看,首先这个呢,嗯,这个干脆这样子,我们还是把这个代码拿过来好吧。
01:00
把代码拿过来,我们验证一遍,一边讲呢,咱们一边梳理。那走到这里来,那现在呢,我们。诶,我我这个前面这个代码梳理过了没有。啊,已经梳理过了,好,那现在呢,我们来看这个,呃,指针传递的案例,我们叫pointer。Pass。OKDEMO。这是第一个pointer pass。OK,跟着老师思路,我们看这个案例,他会输出什么结果。各位,我们首先include std IO问题,然后呢,我们把这个代码放过来,我们看一下它到底是在做什么事情,好吧,代码其实都非常简单。这是一个函数的声明。他干什么呢?他接收接收一个这样的类型。是不是就是接收指针吧,然后大家看这里面有个I,有个有个I有个number,这是两个整数,不说了,现在这句话是干什么,将将number的地址,地址付给付给谁呢?P没问题,也就是说你现在在脑海里面,你要想到P已经P这一个指针,它存放的是。
02:14
Number的地址,老大看。我先把这个取消。同学们,这个时候我把这个number的地址传给他,可不可以?是可以的,因为你number本身是个特嘛,我把number的地址传给这个特新是OK的。是OK的,好传给它以后,然后一一定要用这个TEST2的时候呢,它就会把这个P传到这里面,然后通过星号P加等于一,诶这个星号P。这个星号P就访问到哪里呢?访问到number的值了。对不对,那这个值其实是同一个,也就是说P它只访问的就是number的值,那么这边加一过后呢,会不会对main里面这个number有影响,肯定有影响,所以说这个地方number就应该变成几了呢?变成91了,能理解不?
03:10
应该是很好理解的,来我们运行一下。来我们我们把这个先注销啊,这边这边都已经注销了哈,这边呢,我们执行一下看效果。看效果哈,其实这个我们已经讲过了。已经讲过的。那我们看到这个确实是等于91了,那为什么等于91呢?就是因为你传的是地址,如果同学们这块还不明白,还不明白的话呢,咱们可以再啰嗦一点点哈,因为这是正式讲指针了,所以说我们可以这样子再给他画一个示意图来说明。他他到底是怎么来玩这个东西的呢?其实可以这样去理解。这个呢,是我们的一块内存。把它拿下来。这个是,诶为什么拿不下来呢?好,这是我们的一块内存。
04:02
内存。那么我们代码呢?实际上是从主函数开始执行的。对不对,那一旦从主函数还开始执行呢,我们可以认为这边有个站。我们知道在内存里面有个空间就是站,这个站里面呢,第一个站就是我们的主方法,这个站对不对,它是独立的。主站,那么主站这边有个I,有个number,你可以理解成I,对我简单画一下啊,因为时间的关系,那么它这边存了一个I,现在是未知的,I现在没有复制,你说I呢,没有复值,它就是空的,诶为什后面我没有用到I啊。我没用到I,我哦,我没用到I,这个I其实没啥用啊,可以去掉。本身也可以去掉,在这里也可以去掉,因为I我在这个程序里面其实是没有使用到的,可以拿掉哈,可以拿掉没什么毛病,那么这个时候I没有用了哈,Number有用,Number呢是一个90放这里面的。
05:00
对吧,但是大家知道90它本身是有一个地址的,比如说0X1122吧,假设我这样写,然后这边写完了过后呢。有一个指针存的是它,那这样在我们这个站里面又出现了一个P,这个P呢,它本身。把这个0X1122放进去了,但他自己还有地址哈。他自己是有地址的,他假设他自己的地址是0X1133。哦,我这样简化大家能看懂哈,也就是说大家可以理解成这这条线就已经是过去了。好,我这里换个颜色哈,相中这个指向它了,然后这边下面这个test的二,一旦调用会出现个什么情况呢?会产生一个新的站。认真听哈,产生一个新的站,这个站呢,就是我们所说的TEST2这个站,这个TEST2站它会把这个P,呃把什么呢?把这个number地址,这个number的地址其实就是0X1122嘛,他传给了谁呢?传给了这个行参这个P,也就是说现在这个行参这个P呢。
06:06
他应该是这样子的,它本身自己肯定是有个空间的,这个空间里面存的就是0X1122。0X112,当然他自己呢也有地址。比如说他自己的例子,0X1166吧,也就是说现在你要想象到它指向了他。哎,这个关系是要一定把它理理清楚的好,然后呢,你在这里面用星号P,星号P其实就返回到这个90了,加一加一显然就是对它进行加,加完了过后这个站就调这个函数调用完毕,调用完毕相当于呢,这个就销毁了。销毁过后呢,他去输出这个number main里面的这个number显然变成91了啊,原因就这样子的,好讲完了。讲完了,那接着我们再来看他还有一个什么方法呢,他说说我这样写行不行,我直接把这个P传进去也可以啊。
07:01
你现在用这种方法调用,这种方法调用和直接传一个number本身的地址是一样的。因为你这个P,你这个P是一个指针,这个指针里面存的。其实就是0X11222嘛,也就是说你用这种方式传的是它这个地方0X112,你用这种方式传的是这个指针保存的这个地址也是0X112,因此效果一样。对不对?那如果说效果一样的话,我问同学们一个问题,在这里我再打印一次number会变成多少呢?是不是number就变成了92了,为什么92呢?因为你上面已经改过一次了,再用TEST2函数再加了一次一,所以变成92了,道理就是这样子的,明白了吗?好,这个就讲完了啊,我们再执行一下,看效果是不是等于92就OK了。答案确实是92。讲完好,紧接着我们再来看还有一种方式呢,就是传递指针呢,是直接传一个数组。
08:06
给这个指针变量也是可以的,数组名本身就代表该数组的首字首地址是不是讲过,因此传递数组的本质就是传递地址,那这样子同学们,我们呢,再看一个案例,让同学们说一下这个结果是什么就可以了,这次内存图我就不画了好不好?内存图我就不画了,来,我们把这个案例先注销,我们再看一个案例,跟上老师思路。这边呢,仍然是一个指针的传递。我们写power pass。DEMO02。好的。好,现在呢,我们。POINTERDEMON2。在下边儿。啊,弹021个是单零一,一个单零二。这个后缀给他改一下。好,我们找到零二号,同样我们先引入STDIO。TIO,好,那现在呢,我把这个代码就拿过来用一下就行了,因为时间的关系我就不写了好吗?没什么难度这东西。
09:06
这些都是个加减乘除,小学小学生都会。好,大家看现在呢,我嗯,我是我们来一起阅读一下这个代码。啊,我们来阅读一下这个代码。AVG1,好,这个呢,我们先注销,我们先看第1AVG2AVG2。好,我们看看这边是不是有问题啊,这边这是一个AVGAVG2,那应该还有一个AVG2在哪去啊,在这没有拷贝过来好两个。好,我们看一下,现在大家看一下这是函数的声明。函数。函数声明。对,这个呢也是函数声明。函数声明。没问题吧,然后现在呢,大家看这两个函数get IG呢,它是这样来记,它有一个做一个说明吧。
10:02
说明,第一个参数是一个,这是一个,它接收一个指针,还有一个传一个size进来,就是AV是一个指针。啊,那么下面呢,还有一种方式也是一样的,他看这里面的代码。我们看第一个哈,我们看第一个。嗯,这有一个int类型的数组,是这样子的,这一个avg,然后呢,它。Get avg2的时候呢,把这一个balance大家看。这个是宿主吗?所以他把这个宿主呢,直接传给了这一个。指针,这是可以的,因为这个根本原因是我们这个数组本身就是一个地址。哎,所以说你看这写的传递一个指向数组的指针作为参数,那这个时候就拿到了,那么我们往里面追。他应该调用这了,诶这个地方他是干在干一件什么事情啊。
11:03
它其实就是在求平均值,看到没有,它首先呢,先便利我们这个数组。对,看这个是不是变力数组,然后求平均值,所以说这个地方呢是可以的。哎,也就是说这个balance balance呢就传进去了。Balance传进去,这这个传进去过后呢,在这个get a里面,这个其实指向的就是我们命里这个main函数里面的一个balance数组,这个能理解不。这个一定要理解哈,不然的话你后面看代码就看不懂了,如果我画个示意图来画一个简单示意示意图的话,应该是这样一个图图形。好,我就在这一个地方画了。好吧。假设说我们这儿又有一个站。又有一个赞。可以怎样理解呢?可以这样理解,当我们去执行这句话的时候,这这有个数组。
12:01
是不是这有个数组啊,所以说你可以理解成在我们这边有个主站。哎,我就快速的画一下好吧。快速的画像这边呢,我们主站里面有一个叫balance的数组。Balance的数组,这个balance数组呢,它指向呃,指向一个数组,比如说这里面有一些数据,一二八九十,90好。写完了,然后呢,他在这个地方传的时候,注意听听听讲哈,这地方他在传这个数组的时候,他是这样传的,是不是这样传的呀。OK,他这样传的。那么他一旦这样传在这个把这个balance,因为数组的名就是代表这个数组的首地址,所以说你可以认为一旦调用这个get average呢,它在这上面,诶有一个新的站,这个站呢,我们叫get average。
13:00
那这里面呢,会有一个。接收他的,呃,一个一个变量是不是。ARAARAR啊好,那就相当于说这个ARRARR它呢,本身有一个地址,他这里面存的是谁呢?他存的就是我们这个balance里面的第一个数的。地址能理解吗?就它存的是这个一的这个地址,假如说假我我我举个例子啊,假如说它地址是0X1122,假如那么这个地方存的呢,就是0X1122。啊,当然了,他本身自己呢,也会有地址的,这个肯定是跑不了的,比如说他自己的地址0X1133。那也就是说,呃,我们这个数组这边呢,它其实就指向了他。哎,就执行它,那我问大家,那我问大家一个问题,那如果说我在这个地方。
14:01
通过AR这个指针去操作数组,其实操作的就是命这个站里面的数组,这个能理解了吧。也就是说这地方其实没有像我们想象的把这个数度拷贝一份到这个新的站里面,没有,它其实就是通过这一个地址指向了这个命函数里面的balance数组,因此呢,你在这个站里面如果通过arr对数组音进行操作,其实操作的就是这个地方的,就是命里面这个数组,也就是说只有一个数组,没有两份两个数组,好,明白这个道理呢,老师就不用再多说了,好吗?就说这个就很简单了啊,就就很简单了,这个代码就非常简单,就是大家看到的老师写的这种方式,就是用这个指针看。看到没有,我用这个星号指针这个第一次取的就是谁呀,如果这样来取的话,是不是就取出了我们这这里面第一个数一啊,然后呢,大家看这个是不是我们指针的一个加价运算。
15:05
指针的加加运算能理解吗?其实刚才刚刚就讲过了加加运算。这个ARAARR加加运算呢,它会导致什么变化,是不是它会导致这个地方的指向会加一个四啊。加一个四就会指向这个元素了,就假如说这个元素是0X,呃,112加四就是二六,那你加一次这边呢,就变成了六。OK,那么它一旦变成六过后呢,各位同学,它一旦变成六过后,它再次操作的时候,它操作的就是二这个值了,能理解了吧?啊所以说他这样子呢,通过这个指针可以呃来操作我们这个数组,那就加加就完事了。啊,最后求平均值。啊,这这是可以的,那么上面这个案例呢,这个get I VG呢比较简单,它是通过什么呢?他说我也可以通过这个AR的这个下标来访问,你看也就是说我们不通过这个加加我们这样写。
16:15
零这个呢,其实它就是取得取得那个数组的第一个元素的地址,等到这个I再来加一个,因为你加加嘛,如果是AR。一一呢,诶它就说你虽然没有加加,但是你这个下标改成了一个一也是允许的,因为你本身这个AR2指向的其实就是一个数组嘛,这个大家应该能理解。AR它第一次其实就是指向这个数组的首地址嘛,所以说我在这个地方用用这个用这个什么呀,一个是AR加加可以来改变这里面的值,我也可以通过AR什么呢?这个下标来,这个下标来访问,比如一二也可以访问到我这边不同的这个这个这个值。
17:08
OK。明白吧,但是有一点呢,同学们有1.ar加加会改变它这里面的值。再说一遍,R加加会改变这个名字,但是AR如果你是AR1 ar2并不会改变这个,这个值能理解了吗?这点大家一定要认真领会,因为它是通过这个下标来访问的,他就直接通过这个AR2去。AR这个把这个就是相当于说把这个ARR1的地址拿到了,但是他不去改变这里面的这个值了,大家可以看一下是不是这样子的。好,这两个还是有些变化,就是这个地方呢,AR本身的地址会变化,但是上面你用这个方式来看呢,ARAR的本身的这个地址就是这个这个地方的地址并并,就是说这个地方的地址并没有发生变化。
18:03
OK,相当于说他是通过这个下标直接来取得最新的地址,我可以给他试一下。那么我我怎么来试呢?嗯,好,我们先运行一下这个结果哈,那嗯,算了,这个不用运行,这个结果肯定是正确的,先给大家运行一下,我先在这儿运行一下。我在这呢,每移动一次,我看看AR的本身的地址存放啊,存放的地址是不是变化了,这个肯定在不停的变化。写到这,说说清楚好吧。为了好看呢,我打一个斜杠好吧。那这个要取的话就是arr了,他每次都在不停的变化,那么这样子我们在前面打,为什么前面的你加加了到时就不好打了。好,我们先看看它应该会打,每次增加一个四好,现在调用的就是get的I2,我们运行值好吧。先把这个注销了,跑一个。看效果啊,同学们。
19:01
认真看,认真看。好,我们看看这个结果跟我们想的是否一样呢?好,同学们可以看到这个地址啊,的确是这样子的,你看。48C04是不是在不停的增加呀,但嗯,这这说明这说明这个这个AR呢,这种就是我们刚才讲的这种方式,它会对。这个AR存放的地址发生变化,会对什么呢?会对AR存放的存放的这个地址地址,嗯做标呃做修改,做修改。但是上面这种方式呢,上面这种方式呢,它不会,它不会,那为什么不会呢?我们来看一下啊,也给同学们打印一下就可以了,来在他这个嗯,处理之前,第一个是零嘛,Print f,我我把这个拿过来。好,我们我们仍然打出这个AR存放的地址,你会发现呢,它始终是这个,呃,这个始终是我们这个数组的第一个元素的地址,它并不会像我们想象的那样,每次都来加一个四,为什么呢?因为它是通过下标来走的,不是通过改变arr本身存放的值来走的,好不好,这样大家是不是有点绕啊,其实也不绕,对不对,我把这个改成。
20:25
大家看我改成了盖average,那它调用的就是这这个方法了,指的就是下面这个代码好不好。好,我们运行一下,还是老规矩,来各位同学看效果看效果哈。看效果来走一个。要走一个。好,走起来,我们可以看到的确是这样子的,你看。是不是?那有些同学老师到底他是怎么来做的呢?你可以这样理解,你可以这样理解,就是呃,你你可以这样理解,好,我教大家怎么理解这个东西。A2这个零呢,你可以认为就是A2加上一个零。
21:05
零零好,那当他做这个A1的时候呢,你可以理解成是AR加上了一个一。一个int的。一个int的。因为你下标这个一代表一个int嘛,一个一个一个int的字节。自检。OK,字节那一个字,一个int的字节当然就是四个字节了,一个int不占四个字节吗?好,当你做这个AR。二的时候呢,它其实是AR加上了两个。两个in特的字节,那当然就八了,其他以此类推,大家有没有发现你这种操作其实是AR加多少,但是对AR本身没有变化,你AR加,加的本质是什么呀?是arr等于arr加上一个。
22:06
一个字节或者加四个字节这样这样走的,那这样子呢,会把它值重新覆盖了,你这样写是不是把这个值交给了这个这个变量,然后再把这个变量付给了some,当然你就对AR本身没有变化了,理解了吗?好,我我想我已经讲的够细的了,好,我想我应该讲的够细了,再讲细的话就没有意思了。好各位同学,那关于传递指针这个类型,呃,就是传递指针地址给函数,我们就讲到这,我们把它梳理一下,应该很好理解了,这个示意图都有哈,梳理一下各位同学。这个呢,因为有一点难度,容易引起误会,所以说我讲的稍微慢了一点。但是我们讲清楚了就可以了。慢不是问题,关键是要讲清楚,好,这是我们讲的传递指针,先做了一个基本介绍,然后呢,我们这边是不是举了一个案例啊。对,举了案例了,大家走起来,那第一个案例看一下。
23:02
第一个案例啊,第一个案例里面呢,有内存布局,还有代码输出,我们就放在一起了。好,我把它放在一起啊,代码演示,那具体来说这个代码呢,其实就是我们的第一个案例。对吧,我把它复制到我们的笔记中去好吗?对。那这边是不是还有一个相应的这个内这个分析图啊,对代码的这个内存分析图,内存分析图,那么这个内存内存分析图呢,其实。其实就是这个图。其实说白了就是这个这个图。诶,我这个图为什么不出来。是不是就这个图啊。诶把这个也拿过来,其实就是这块,关键点就在这块对不对。大家只要把这个理解了,就完全的OK。那么紧接着呢,是不是我们又讲了,呃,一个案例就是传数组,因为传数组呢,它比较特别,它本身这个名字就代表一个地址,对不对,所以说你不需要再取地址符了。
24:05
好的。这句话,然后这边我们也有内存布局图,还有它的一个代码输出效果,是不是同学们挺简单的。好,然后呢,我们把代码演示。代码代码H代码演示。代码演示呢,老规矩,我们从这边把代码拿过来就可以了。对不对,这边也做了相应的分析。相应分析好,那么相应分析这边呢,分析的内存布局图也给大家拿过来,在哪里呢?在这边。是不是这个图啊,其实挺简单的。好,放到这儿就OK了。最后呢,我这还有个问题需要同学们来回答一把,哪一个问题呢?大家看,问问如果在get avg函数中通过指针修改了数组的值,那么main函数中的balance数组是否会相应的变化?请回答会不会?
25:04
肯定会呀,你如果在这里,在这里面你指向它,你把这个一加一个一,那主函数里面的balance肯定修改了,说答案是能。会的啊就会的,为什么呢?因为因为因为get average。Average函数的函数,指针函数。中的这个指针指向的指向的就是哪个呢?命函数的数组肯定会修改好,这个答案呢,我就分享到这里,好吧,这一个问答题也放到这。我就是一个。思考题思考题。思考题呢,我也给大家编一个号就可以了,非常的简单哈。来,走到这。好,梳理一下。梳理一下。各位,关于我们这个章节传递指针或者叫地址给函数,就给大家讲解到这里比较重要,相对有一点难,大家好好的消化一下。
我来说两句