C 传递所有内容按值。您将head 传递给insert_back 函数,它是一个空指针(如值NULL)。
此 NULL 分配给该值的 head 参数变量。
您正在更改 insert_back 函数的本地变量,这很好,但也不要期望更改 main 函数中的变量。
有两种可能的方法:
要么添加第二级间接(将指针传递给要更改的变量),要么返回 head 变量,然后重新分配:
指针对指针:
void insert_back(NODE **head, int val)
{
NODE *node = malloc(sizeof *node);
if (node == NULL)//check if malloc was successful!
exit(1);//or fprintf(stderr, "message"); and handle the issue
node->val = val;
node->next = NULL;
if (*head == NULL)
{
*head = node;
return;
}
NODE *tmp = *head;
while (tmp->next != NULL)
tmp = tmp->next;
tmp->next = node;
}
像现在一样调用这个函数,但是传递指针的地址,而不是指针本身:
NODE *head = malloc(sizeof *head);
if (head == NULL) exit (1);
head->next = NULL;
insert_back(&head, 123);
返回head:
NODE * insert_back(NODE *head, int val)
{
NODE *node = malloc(sizeof *node);
if (node == NULL) exit (1);
node->val = val;
node->next = NULL;
if (head == NULL)
{
return node;//head is null, no need to assign
}
NODE *tmp = head;
while (tmp->next != NULL)
tmp = tmp->next;
tmp->next = node;
return head;//return node passed initially, because it will be reassigned!
}
//call like so:
head = insert_back(head, 123);
作为一个额外的好处,你也可以使用这个函数来分配一个新的结构:
NODE *head = insert_back(NULL, 123);//pass null pointer, will return new node and assign it to head
但是,同样有效:
NODE *head = insert_back(NULL, 123);
head = insert_back(head, 456);
head = insert_back(head, 789);
printf("Head: %d\nNext: %d\nTail: %d\n",
head->val,
head->next->val,
head->next->next->val
);
当然,别忘了写一个像样的函数来释放你的链表。
也许,如果你还没有写过这个,这里有一个基本的例子(同样:两种方法都可以使用,但我建议使用指针到指针的方法):
void free_list(NODE **list)
{
if (*list->next == NULL)
{//tail
free(*list);
*list = NULL;//assign NULL, makes a valid NULL pointer
return;
}
free_list(&(*list->next));//recursive call
//once we get here, all next-nodes are freed:
free(*list);//free node, and again:
*list = NULL;//make a valid null pointer
}
//call:
free_list(&head);
free(head);//will not be a problem, head is NULL pointer
或者:
void * free_list(NODE *list)
{//note VOID POINTER is returned (will always return NULL, though)
if (list->next == NULL)
{
free(list);
return NULL;
}
free_list(list->next);
free(list);//free node, and again:
return NULL;//make a valid null pointer
}
//call
head = free_list(head);
free(head);//not an issue here
所以两者都同样安全,您可能会想,但是如果您忘记分配第二个 free_list 函数的返回值怎么办?
free_list(head);
free(head);//<--X undefined behaviour
head 指向的内存已被释放,但您正在第二次调用free。这会让你很伤心:head 指针无效,将无效指针传递给free 会导致未定义的行为。这就是为什么第一种(指针对指针)方法是更安全的选择:该函数一旦编写,将永远不会忘记将 NULL 分配给指针。
顺便提几点建议:
您的 main 函数不返回 int。使用-Wall 编译此代码并通过添加return 0; 语句来解决该问题。
查看所有函数的返回值,包括malloc&co,如果分配失败,则返回NULL。您没有对此进行检查,因此存在未定义行为的风险。