最近因为一些原因重新打开了c语言的大门,很快就来到了死亡指针这一部分。一番探查之后发现,它一点也没变,当然,难度也一点都没变。好在有之前的底子,也是较为迅速的回忆起来了,就在以为已经再次拿捏的时候,一道题直接来了一个大逼兜。
![](https://i-blog.csdnimg.cn/blog_migrate/862f6e913a2e8ce4b783ecc36ec92d47.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d1f93f03f357e0dc1d9968e7aa5d807b.png)
写了这样一个循环双链表,想要实现的是,传入一个定义好的头节点,然后在其中申请空间,完成首位指向,返回布尔值,作为创建成功的标志,一套操作行云流水,看起来也算是优雅,直接编译运行猛如虎,定睛一看....,查看之后是发现在插入到链表中的时候空指针了。
![](https://i-blog.csdnimg.cn/blog_migrate/3fe21800539191918e59384085fc8cde.png)
好呗,按照“我们不生产bug,我们只是bug的搬运工“原则,立马打开我们的调试工具,开始步入步入步入。在初始化链表的时候,好似成功的开辟了一块空间,但是看地址,head和headCopy实则毫无关系,所以在后边进行连接的时候,我们的head其实没有指向期望的结构体,所后边使用结构体的内容时自然空指针了!
![](https://i-blog.csdnimg.cn/blog_migrate/b30e018ee1a1210a42caf8b3fa04ef85.png)
仔细看刚进入的时候,两者的指向还是一样的,但是两者的在内存中的差了有一点远。
![](https://i-blog.csdnimg.cn/blog_migrate/73c5bdb6f2bf9814ec0a9c78575ccb33.png)
所以后边在退出Init方法的时候,head并没有如我们所愿。
发现了问题,那就好办了,直接开办,我的解决思路有两个:
(1)既然两者的内存地址不同,那就将headCopy作为返回值返回回去,赋给我们的head----冤大头节点,但是这样就要改变原来的优雅结构(自认为的优雅),所以pass了。
(2)请出伟大的引用变量,在传入的形参名前加上&,使其成为我们的引用变量,然后再调试看地址,就完美
bool linkListInit(LinkList & headCopy) {
headCopy =(LinkNode*) malloc (sizeof(LinkNode));//创建一个节点
if(headCopy==NULL) {
return false ;//内存不足分配失败
}
headCopy->next=headCopy;//让其前驱和后继都指向自己
headCopy->prior=headCopy;
return true;
}
![](https://i-blog.csdnimg.cn/blog_migrate/f66dc1e36cc819ea436355482894b0d2.png)
至此,此次问题就算是解决了,后续各个功能都流畅运行。
但是,在我之前的理解中,高贵的指针类型传递的是地址呀,既然传递的是地址,会函数内外无法同步呢,通过查(咨)阅(询)资(大)料(佬),对于指针充当参数又有了一点新的理解。
我们都知道每一个变量都是要占用一定内存空间的,同时也是有自己的作用域的,而我们的函数传递遵循的是值传递,即使对于高贵的指针也是如此。
我们的函数在被调用的时候,会为自己方法体中的变量等内容去堆栈中申请一片内存空间,所以他们可不是谁的附庸,谁的影子,他们是实打实的真变量,也是有自己地址的。即使机缘巧合之下,形参和实参名字一样,那也只是看起来一样,在计算机中我们的区分是否相同,不能看是否同名,最根本的应该是要看是否放在同一块内存中,也就是地址是否相同。这也是为什么我们的一般情况下,某一个方法内的操作产生的影响无法延伸到其作用域外,两者地址不同,本身就是萍水相逢,只不过是命运的巨手把二者推到了一起,没有承诺期限。再者方法函数调用完毕后,堆栈中的内存将被收回,局部变量将被销毁,一切都将消散,最后一点点连接也要给人割断,那短暂的连接就好像是主调函数的做了一个梦,既然是梦,那总是要醒的,既然是梦里的发生的,那还能当真吗?
我们之所以可以通过指针充当形参对函数外的指定变量进行修改,那是因为这个指针将其指向的地址通过值传递传给了函数中的局部变量,通过对地址的操作,完成不可描述的操作,这个过程也是严格的遵循值传递的。
最后在来看看我们的引用类型,这里的&可不是取地址的意思,它姑且可以称之为取别名符,相当于是给我们的变量(内存地址)来一个花名,当然,只要愿意,十个一百个花名也是理论允许的,通过上微机原理等课程以及我上面的讲解,地址操作算是最底层的操作,不过名字有多花,只要是内存地址相同,操作就是同步的,这也是我上面第二种解决思路的出发点。
好,今天解决一个宇宙难题,奖励自己摸鱼1分钟。
奋斗趁年轻,吃苦趁现在!