双向链表函数调用问题:insertAtBeg调用addToEmpty失败原因及解决
问题描述
我实现了向空双向链表添加节点的addToEmpty函数,该函数接收struct node**类型指针参数,在main函数中传入&head调用可正常运行。随后编写在链表头部插入节点的insertAtBeg函数,当检测到链表为空(*ptr == NULL)时,尝试调用addToEmpty(&head, 10)却无法正常工作,尝试修改head前的符号(如*、**或不加符号)仍无效,请求解释原因并解决问题。
相关代码
addToEmpty函数
void addToEmpty(struct node **ptr, int value) { struct node *newNode; newNode = (struct node *)malloc(sizeof(struct node)); newNode->prev = NULL; newNode->data = value; newNode->next = NULL; (*ptr) = newNode; }
main函数调用示例
int main(void) { struct node *head = NULL; addToEmpty(&head, 10); return 0; }
出现问题的insertAtBeg函数
void insertAtBeg(struct node **ptr, int value) { struct node *newNode; newNode = (struct node *)malloc(sizeof(struct node)); if(*ptr == NULL) // 如果链表为空 { addToEmpty(&head, 10); // 这里无法正常工作 } else { newNode->data = value; (*ptr)->prev = newNode; newNode->next = *ptr; (*ptr) = newNode; } }
我试过把&head改成*head、**head或者直接写head,但都没用,完全搞不懂为什么会这样。
问题原因与解决方法
核心原因
你在insertAtBeg里直接写&head是错误的——head是main函数的局部变量,insertAtBeg根本访问不到它!
insertAtBeg的参数ptr本身就是main里head的地址(调用时传的是&head),所以你不需要再找head的地址,直接把ptr传给addToEmpty就行。
另外还存在两个小问题:
insertAtBeg里不管链表空不空都提前malloc了newNode,如果走空链表分支,这个newNode会变成内存泄漏。- 调用
addToEmpty时写死了10,应该用函数参数里的value。
修正后的insertAtBeg函数
void insertAtBeg(struct node **ptr, int value) { if(*ptr == NULL) // 如果链表为空 { addToEmpty(ptr, value); // 直接传ptr,它就是head的地址 } else { struct node *newNode = (struct node *)malloc(sizeof(struct node)); newNode->data = value; (*ptr)->prev = newNode; newNode->next = *ptr; newNode->prev = NULL; // 新头节点的prev必须设为NULL (*ptr) = newNode; } }
补充说明
- 为什么传
ptr就行?因为ptr的类型是struct node**,正好匹配addToEmpty的参数类型,而且ptr指向的就是main里的head指针,addToEmpty里修改(*ptr)就是在修改main的head。 - 把
malloc移到else分支里,避免空链表场景下的内存浪费和泄漏。 - 新头节点的
prev必须设为NULL,保证双向链表的结构正确。
内容的提问来源于stack exchange,提问作者dynamitri
相关产品推荐
相关产品推荐

