C语言链表中释放内存函数的问题,请高手解答。
//结构定义typedefstructnode{intitem;structnode*next;}Node;typedefNode*List;//释放内存函数voidFr...
//结构定义
typedef struct node
{
int item;
struct node *next;
}Node;
typedef Node* List;
//释放内存函数
void FreeMem(List *list)
{
Node *p=*list;
Node *pt=NULL;
/*----------可行----------*/
while(p!=NULL)
{
pt=p->next;
free(p);
p=pt;
}
/*-------------------------
为什么用这种方式操作会出错?
while(p!=NULL)
{
list=&p->next;
free(p);
p=*list;
}
-------------------------*/
}
看看我哪里理解错了。
FreeMem(List *list);这样的定义list是指向一个节点的指针的指针。
*p=*list;是把节点的指针值复给p。p现在指向了第一个节点。
list=&p->next;将下一个节点指针的地址(也就是指针的指针)复制给list这个二级指针。现在list指向了第二个节点指针的地址。
free(p);p现在还是指向第一个节点,释放第一个节点的内存。
p=*list;现在将第二个节点的地址复制给p,使p指向第二个节点。
如此循环。
不知道哪里错了? 展开
typedef struct node
{
int item;
struct node *next;
}Node;
typedef Node* List;
//释放内存函数
void FreeMem(List *list)
{
Node *p=*list;
Node *pt=NULL;
/*----------可行----------*/
while(p!=NULL)
{
pt=p->next;
free(p);
p=pt;
}
/*-------------------------
为什么用这种方式操作会出错?
while(p!=NULL)
{
list=&p->next;
free(p);
p=*list;
}
-------------------------*/
}
看看我哪里理解错了。
FreeMem(List *list);这样的定义list是指向一个节点的指针的指针。
*p=*list;是把节点的指针值复给p。p现在指向了第一个节点。
list=&p->next;将下一个节点指针的地址(也就是指针的指针)复制给list这个二级指针。现在list指向了第二个节点指针的地址。
free(p);p现在还是指向第一个节点,释放第一个节点的内存。
p=*list;现在将第二个节点的地址复制给p,使p指向第二个节点。
如此循环。
不知道哪里错了? 展开
4个回答
展开全部
首先你要搞明白,List本身已经被定义为Node*类型,因此List*实际上是一个二级指针
你的疑问中,如果改成*list = p->next,运行应该是可以通过的。但是不推荐这样做。为什么呢?
这就要先理解FreeMem这个函数,为什么用List*做参数,而不是List。如果只是为了释放链表内存,只要一级指针就可以了,用二级指针只会增加代码的复杂程度,降低可读性。二级指针的作用就在于,在这个函数内,你可以修改这个函数的主调函数(比如main函数)中链表头结点的指针值。在这个例子中,显而易见的就是,链表释放了内存,head指针应该是NULL。
如果上面这段话你能明白的话,那么我的建议是,使用你问题中“可行”的那段代码,并添加*list = NULL;在结尾。或者这样做也可以达到同样的效果:传入参数使用一级指针,配合函数的返回值来保证功能的完整性,这样调用的时候需要诸如head = FreeMem(head);以达到释放内存后置head指针为NULL的目的。
看了楼主的追问,看来楼主对二级指针的理解还不太到位。其实mornslit兄的解释已经说清楚你这种写法的问题在哪了。我再帮你分析下:
pt = p->next;
*list = p->next;
这两种写法,效果是一样的,都是保存了下一个节点的地址(也就是p->next的值)
list = &p->next;
这种写法,是保存了p这个节点的next指针的地址,通过*运算,看似可以获取next的值,其实在p被free掉之后,next指针本身的值已经不能保证了
简言之,你错在哪了:p->next是下一个节点的地址,是与p共存亡的,你可以保存p->next的值,但不应该保存它的地址
说实话,还是建议楼主先搞清楚为什么要用二级指针,杀鸡用牛刀未必一定好~
你的疑问中,如果改成*list = p->next,运行应该是可以通过的。但是不推荐这样做。为什么呢?
这就要先理解FreeMem这个函数,为什么用List*做参数,而不是List。如果只是为了释放链表内存,只要一级指针就可以了,用二级指针只会增加代码的复杂程度,降低可读性。二级指针的作用就在于,在这个函数内,你可以修改这个函数的主调函数(比如main函数)中链表头结点的指针值。在这个例子中,显而易见的就是,链表释放了内存,head指针应该是NULL。
如果上面这段话你能明白的话,那么我的建议是,使用你问题中“可行”的那段代码,并添加*list = NULL;在结尾。或者这样做也可以达到同样的效果:传入参数使用一级指针,配合函数的返回值来保证功能的完整性,这样调用的时候需要诸如head = FreeMem(head);以达到释放内存后置head指针为NULL的目的。
看了楼主的追问,看来楼主对二级指针的理解还不太到位。其实mornslit兄的解释已经说清楚你这种写法的问题在哪了。我再帮你分析下:
pt = p->next;
*list = p->next;
这两种写法,效果是一样的,都是保存了下一个节点的地址(也就是p->next的值)
list = &p->next;
这种写法,是保存了p这个节点的next指针的地址,通过*运算,看似可以获取next的值,其实在p被free掉之后,next指针本身的值已经不能保证了
简言之,你错在哪了:p->next是下一个节点的地址,是与p共存亡的,你可以保存p->next的值,但不应该保存它的地址
说实话,还是建议楼主先搞清楚为什么要用二级指针,杀鸡用牛刀未必一定好~
展开全部
while(p!=NULL)
{
list=&p->next; //这句话的意思是把p结点的next域的地址赋给list,list实际指向将要被释放的内存空间
free(p); //p结点释放,list就失效了
p=*list;
}
{
list=&p->next; //这句话的意思是把p结点的next域的地址赋给list,list实际指向将要被释放的内存空间
free(p); //p结点释放,list就失效了
p=*list;
}
追问
FreeMem(List *list);这样的定义list是指向一个节点的指针的指针。
*p=*list;是把节点的指针值复给p。p现在指向了第一个节点。
list=&p->next;将下一个节点指针的地址(也就是指针的指针)复制给list这个二级指针。现在list指向了第二个节点指针的地址。
free(p);p现在还是指向第一个节点,释放第一个节点的内存。
p=*list;现在将第二个节点的地址复制给p,使p指向第二个节点。
如此循环。
不知道哪里错了?
追答
*p=*list;这句话你断章取义了。全句是Node *p=*list,实际分两句:Node *p; p=*list;定义一个指向Node的指针p,然后把双重指针list的值(也就是头指针指向的地址)赋给p,这样p指向链表头。
逻辑上list=&p->next是把指向第二个结点的指针的地址赋给list了,问题是,这个指向第二个结点的指针存在于即将被释放的结点内,这个结点一旦被释放,list就指向了一个已经被释放的空间,那么*list的值就是无效的了。
本回答被提问者和网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
//结构定义
typedef struct node
{
int item;
struct node *next;
}Node;
typedef Node* List;
//释放内存函数
void FreeMem(List *list) 这里就有问题了,List已经是指针了,把*去掉
{
Node *p=*list; 同理。把后面的*去掉
Node *pt=NULL;
/*----------可行----------*/
while(p!=NULL) 链表有头指针吗?如果有的话这里不行,
{ 需要将p指向list->next
pt=p->next;
free(p);
p=pt;
}
/*-------------------------
为什么用这种方式操作会出错? 看不懂你这里是干嘛?list一直指向同一块地址
while(p!=NULL) 把p指向的地址释放了,list指向的也就释放了
{
list=&p->next;
free(p);
p=*list;
}
-------------------------*/
}
typedef struct node
{
int item;
struct node *next;
}Node;
typedef Node* List;
//释放内存函数
void FreeMem(List *list) 这里就有问题了,List已经是指针了,把*去掉
{
Node *p=*list; 同理。把后面的*去掉
Node *pt=NULL;
/*----------可行----------*/
while(p!=NULL) 链表有头指针吗?如果有的话这里不行,
{ 需要将p指向list->next
pt=p->next;
free(p);
p=pt;
}
/*-------------------------
为什么用这种方式操作会出错? 看不懂你这里是干嘛?list一直指向同一块地址
while(p!=NULL) 把p指向的地址释放了,list指向的也就释放了
{
list=&p->next;
free(p);
p=*list;
}
-------------------------*/
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
list=&p->next;
改成
list=&(p->next);
试试看
改成
list=&(p->next);
试试看
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询