typedef struct Node
{
int data;
struct Node *next;
}LNode,*LinkList;
这里LNode等价于struct Node LinkList等价于struct Node*。
对于链表的初始化可以有一下的三种方式
void InitList(LinkList& L);
void InitList(LinkList* LL);
LinkList InitList();
在这里我们一个一个的分析:
对于第一个InitList(LinkList& L) 的实现方式如下,这里如果去掉&则会出现报错的情况。L是一个指针,传入地址就行了,为什么还要加引用?
void InitList(LinkList& L) { //这里L使用引用传递
L = (LinkList)malloc(sizeof(LNode));
if (!L){
return;
}
L->next=Null;
}
在主函数中
void main(){
LinkList L = NULL;
InitList(L);
printf("%d",L->data);
}
这里如果没有&,错误的原因是
主程序里的LinkList L = NULL(假设为A),被分配一个空间,这个空间是在main函数的那段栈里,里面的值为Null.主程序调用InitList(L)时,L为实参,它把它的值null,赋给形参。这个时候,内存里有两个LinkList类型的变量(假设为B),一个是A,一个是B; A,B的值都是null;在你的子函数里,L =(LinkList)malloc(sizeof(LNode)); 这个时候,B的值发生改变,变成指向你新开辟的内存区域;A的值还是不变,仍然是空,子函数出来的时候,B出栈,再也没有指针指向你开僻的区域,引起内存泄露。接着,主序printf("%d",L->data),这个L为标记A,值是NULL ,NULL->data肯定出错。
对于第二个InitList(LinkList* LL),这里的LinkList就是一个等价于struct Node*的指针,为什么也有一个*,那这时候LL岂不是指向指针的指针?
void InitList(LinkList* LL) { //这里LL使用指针传递
*LL = (LinkList)malloc(sizeof(LNode));
if (!*LL){
return;
}
(*LL)->next = NULL;
}
LL的确就是指向指针的指针。这样用的原因和上面是一样的。 用指向指针的指针LinkList* LL;调用子函数的时候,内存里有一个L,和一个LL两个指针变量。L的值是空,LL的值是L的地址,*L就是L本身了,退出子函数后也不会引起Null指针的问题。
第三个就没什么解释了。通过返回值来传递参数
LinkList InitList() { //通过返回值传递
LinkList L = (LinkList)malloc(sizeof(LNode));
if (!L){
return;
}
L->next = NULL;
return L
}
总结:一般情况下,向函数传递指针类型的参数,可以让函数改变指针指向的内容,并且将改变的效果返回。在这里要改变指针变量L本身的值,而不是L所指向的内容的值(函数中有malloc()这个函数改变了L的值),故这里要么向函数传递L的引用,要么就是传递指向L的指针。