学习链表定义过程中有一些疑问:
- 不明白定义变量的时候LNode和LinkList的区别;
- 不明白调用创建链表函数之前已经定义了LinkList L,为什么在函数内还要再分配一次内存;
- 不明白创建链表函数中为什么要在LinkList后加&。
网上搜了各种答案无果,于是自己动手跑了一遍代码,通过调试以下代码有了初步认识,记录一下:
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
int data;
int data_x;
int data_y;
struct LNode *next;
}LNode,*LinkList;
int CreateLink_L(LinkList &L,int n){ // 问题:为什么这里要加&
// 创建含有n个元素的单链表
LinkList p,q;
int i;
int e=5;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;// 先建立一个带头结点的单链表
q = (LinkList)malloc(sizeof(LNode));
q = L;
for (i=0; i<n; i++) {
p = (LinkList)malloc(sizeof(LNode)); // 生成新结点
p->data=e;
p->next=NULL;
q->next=p;
q=q->next;
}
return true;
}
int main()
{
LinkList T;
LNode *p;
LNode q;
int a = sizeof(T);
int b = sizeof(p);
int c = sizeof(q);
int n=3;
if(CreateLink_L(T,n)) // 判断链表是否创建成功,请填空
{
printf("A Link List Has Created.\n");
}
}
(代码引自:https://blog.csdn.net/u012515510/article/details/24997837)
首先是第一个问题,定义变量的时候LNode和LinkList有什么区别,调试过程中发现a, b, c = 8, 8, 24(至于为什么是这个数确实搞不清楚,有大神明白可以给指点一下),并且增删结构体中的data变量对c的大小有影响,对a, b无影响。结论是定义变量的时候,LinkList等同于LNode*,可以理解为只是定义了一个能指向LNode类型的指针,而LNode则是定义结构体本身。
搞明白第一个问题后面的问题就很简单了,既然定义LinkList只是定义了一个指向LNode类型的指针,在创建链表时自然要新开辟一块内存,不然没有地方存放data和*next。这一点通过调试q的值也可以证明:在声明q后,就等于分配了一块sizeof(LNode)大小的内存,即使不做任何事(调用malloc或者初始化)也可以看到q的data域和*next域是有值的(内存遗留的脏数据?),而T和p就没有data和*next。
最后一个问题在代码引用的文章里博主已经解释了:一般情况,向函数传递指针类型的参数,可以让函数改变指针指向的内容,并将改变的效果返回;这里要改变指针变量L本身的值,使它指向新开辟的内存空间L = (LinkList)malloc(sizeof(LNode)),而不是要改变L所指向的内容的值,所以,要么向函数传递L的引用,要么传递指向L的指针(指向指针的指针)。即如果不加引用,函数执行完毕后头指针还是指向一个不知名的地址。