此函数将获取链表的特定节点并使其成为最后一个节点。
void lastNode(struct list *node)
{
struct list* temp = node->next;
node->next = NULL;
struct list* temp2;
while(temp)
{
temp2 = temp->next;
printf("%p \n",temp);
free(temp);
temp = temp2;
}
}
int main()
{
struct list d={4,NULL};
struct list c={3,&d};
struct list b={2,&c};
struct list a={1,&b};
struct list *node = &a;
lastNode(&b);
while(node)
{
printf("%d \n",node->d);
node=node->next;
}
return 0;
}
但它在释放节点方面给我错误。
答案 0 :(得分:1)
更新:这是在提供免费功能的来电之前写的。现在我看到了,我会说是的,你不能在堆栈地址上调用free
。但是我的原始答案保留在下面,关于如何更好地删除列表......
我没有看到突然出现free
错误,但......看起来这种方法只有在传入的node
是第一个节点时才有效。如果它是除第一个节点以外的某个节点,则需要指向前一个节点,因此您可以设置prev->next = node->next
。
实际上,更多地考虑这个...如果你所做的只是拿一个节点并将其作为最后一个节点,为什么你需要free
什么呢?看起来这段代码从temp
开始释放整个列表。如果这是你的意图我推荐更像这样的东西:
void free_all_at_node(struct list **list, struct list *node_to_free)
{
struct list *n = *list, *prev = NULL;
// Search for node_to_free, updating prev to indicate the last node we saw.
//
while (n && n != node_to_free)
{
prev = n;
n = n->next;
}
// Check to see if we found it...
//
if (n == node_to_free)
{
// Do we have a previous node?
//
if (prev)
{
// Yes, update next pointer...
//
prev->next = NULL;
}
else
{
// This is the start of the list. Update the head...
//
*list = NULL;
}
// Now free stuff...
//
while (n)
{
struct list *next = n->next;
free(n);
n = next;
}
}
}
假设您希望node_to_free
成为第一个释放的节点,因此我们会在列表的开头搜索它。另一种方法是让调用者在第一个节点之前指定节点。 (看起来你的代码实际上是在尝试这样做......)我可能更喜欢这样做:
void free_after_node(struct list *n)
{
// If the node is NULL or has no next node, there is nothing to do.
//
if (n && n->next)
{
// Start at the node after the first, since we want to keep the first
// one around.
//
n = n->next;
// Now free...
//
while (n)
{
struct list *next = n->next;
free(n);
n = next;
}
}
}
答案 1 :(得分:1)
查看完整代码:
struct list c={3,&d};
struct list b={2,&c};
lastNode(&b);
free
temp
不合法,因为它未使用malloc
分配。
struct list* temp = node->next; /* temp is now &c. You can't free it. */
while(temp)
{
/* ... */
free(temp); /* Tries to free &c which is on the stack. */
}