问题来源:
《大话数据结构》书中有关单链表的写法疑问,正如http://www.cnblogs.com/cj723/archive/2011/06/15/2081574.html该链接270楼的人所说的对于LinkList的疑问,为啥不用LinkList P来作为函数的形参。作者写得很清楚,但是我还是不是很明白,因此查了网上的一些关键字。
#270楼
查网上关键字,看到以下链接加深对指针的指针的了解。
http://www.cnblogs.com/qqingmu/archive/2007/09/19/898125.htm
还有指针的指针在百度的回答
http://zhidao.baidu.com/link?url=kFEtxBEgZhJ57sBMzo56YqlJ9nbHZ7ki1Y1_g5e6GCY0zPgiBobcD5oYQ049rpcv8_91TOHB8twpm71-a6WBUa
里边的回答是:
您既然对指针有定义上的了解,那么理解指针的指针也不会很难
关键认识清楚,指针变量也是一种变量,有着自己的值和它自身在内存中的地址
例如int a=6,我们假设它在内存中地址为1276AF73,而值为前面赋给的6
下面定义一个指针
int *p=&a;
将指针变量p指向了a,那么p这个变量的值就是a的地址1276AF73,而它自身又有自己在内存中的地址,我们假设为1234FE34.
同样的道理,我们可以定义一个新的指针变量,让它指向指针变量p:
int *q=&p;
关键认识清楚,指针变量也是一种变量,有着自己的值和它自身在内存中的地址
例如int a=6,我们假设它在内存中地址为1276AF73,而值为前面赋给的6
下面定义一个指针
int *p=&a;
将指针变量p指向了a,那么p这个变量的值就是a的地址1276AF73,而它自身又有自己在内存中的地址,我们假设为1234FE34.
同样的道理,我们可以定义一个新的指针变量,让它指向指针变量p:
int *q=&p;
这个新的指针变量q的值为p的地址,即1276AF73,而它自身又在内存中也有自己的地址,假设为128974AD
同理,我们可以继续定义下去指向q的指针。。。
这种指向指针变量的指针,我们就称做指针的指针
同理,我们可以继续定义下去指向q的指针。。。
这种指向指针变量的指针,我们就称做指针的指针
进一步,再看指针的指针在程序中运行是如何的?
http://www.cnblogs.com/dzry/archive/2011/05/12/2044835.html
而书本的作者指出,
当指针做参数传递的时候不能用该指针来动态申请内存。详细可以看
http://blog.csdn.net/wuchuanpingstone/article/details/7357545
直接用str指针参数去子函数申请内存,而不用指针的指针去申请申请新内存,那么指针参数在子函数中生成副本p,只是副本p所指的内存地址改变了,而str并没有丝毫改变。
|str|------->|NULL|
|副本p|--------->|新开辟的内存|
原来的指针副本p是和str一样,都是指向NULL空间,后来副本p在子函数中执行新开辟内存,而传进来的指针str则并无丝毫改变。
联想:推而广之,这个道理适用在交换两个数值的函数声明和函数体写法中,很容易出错。
综上理解:
有这么一个定论,如果需要用到生成动态内存的情况,必须使用“指向指针的指针”去申请内存。针对《大话数据结构》里单链表的代码情况,主函数中的
&L就是指向一个指针的地址,而这个指针刚好又指向单链表中的结点,所以是指向指针的指针,而子函数中的
LinkList *L中的
*L在下面函数的操作中就是新申请的结点内存,而L就是指向该结点内存的地址,刚好可以对应起来。
这个原因是因为当指针做参数数,在用这个指针重新分配内存时,会报错,详见<<高质量c/c++编程>>中的指针做参数