下面是我的节点结构声明和后面函数的插入。在main中,我声明一个头节点并将其指向NULL。然后我调用该函数,并尝试打印出第一个节点的值,但程序停止。我仍然无法弄清楚出了什么问题。
typedef struct node {
int val;
struct node *next;
} NODE;
void insert_back(NODE *head, int val) {
NODE *new = malloc(sizeof(NODE));
new->val = val;
new->next = NULL;
if (head == NULL)
head = new;
else {
NODE *p = head;
while (p->next != NULL)
p = p->next;
p->next = new;
}
}
int main() {
NODE *head = NULL;
insert_back(head, 2);
printf("%d", head->val);
}
答案 0 :(得分:1)
当你离开你的函数时,你在insert_back中分配的指针会丢失。为了使它能够工作,你的insert_back应该得到指针指针。
typedef struct node {
int val;
struct node *next;
} NODE;
void insert_back(NODE **head, int val) {
NODE *new = malloc(sizeof(NODE));
new->val = val;
new->next = NULL;
if (*head == NULL)
*head = new;
else {
NODE *p = *head;
while (p->next != NULL)
p = p->next;
p->next = new;
}
}
int main() {
NODE *head = NULL;
insert_back(&head, 2);
printf("%d", head->val);
}
答案 1 :(得分:1)
你需要传递头部的地址,而不仅仅是头部。而不是按值调用使用按引用调用
应该是insert_back(&head, 2);
在定义中更改为void insert_back(NODE **head, int val) {
答案 2 :(得分:1)
C按值传递所有。您正在向head
函数传递NULL
,这是一个空指针(如值insert_back
)。
此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
&amp; co,如果分配失败,它将返回NULL
。你没有检查,所以那里存在未定义行为的风险。