C语言链表头插法传一级指针的push函数为何失效?
C语言链表头插函数传参失效问题解析
问题本质
失效的核心原因是C语言所有函数参数均为值传递:函数调用时实参会被拷贝为函数内部的独立局部变量,函数内对局部形参的修改不会同步到外部的原始实参。
可正常运行的参考实现
#include <stdio.h> #include <stdlib.h> typedef struct node { int val; struct node *next; } node_t; void push(node_t **head, int val) { // head是指向「链表首节点指针」的二级指针 node_t *new_node = (node_t *)malloc(sizeof(node_t)); new_node->val = val; new_node->next = *head; *head = new_node; } int main() { // 初始化第一个节点 node_t *head = (node_t *)malloc(sizeof(node_t)); head->val = 2; head->next = NULL; // 头插新节点,必须传入head的地址 push(&head, 1); return 0; }
这个版本调用push时传入&head,也就是main函数中原始首节点指针的内存地址,函数内通过二级指针解引用可以直接修改外部原始指针的指向,因此头插逻辑生效。
修改后版本的失效原因
你修改后的函数实现如下:
void push(node_t *head, int val) { node_t **p_head; p_head = &head; // 这里取到的是局部形参的地址,不是外部原始head的地址 node_t *new_node = (node_t *)malloc(sizeof(node_t)); new_node->val = val; new_node->next = *p_head; *p_head = new_node; }
执行时的问题链路非常明确:
- 调用
push(head, 1)时,main里的原始head指针(指向val=2的首节点)会被拷贝一份,赋值给push函数内部的局部形参head,这是两个完全独立的指针变量,只是初始保存的地址值相同 - 函数内
p_head = &head拿到的是push内部局部形参head的地址,和main里的原始head没有任何关系 - 后续
*p_head = new_node修改的只是push内部局部形参的指向,等函数执行结束,局部变量全部销毁,main里的原始head还是指向原来的首节点,新创建的节点因为没有任何有效指针指向,还会造成内存泄漏。
可以用一个通俗的类比理解:你想让外卖员把餐送到你家,正确做法是给外卖员你家的真实地址(传
&head,二级指针),外卖员能直接找到你家;如果你只是把你家的门牌号抄在一张纸条上给外卖员,外卖员在纸条上改个别的门牌号,永远也找不到你真正的家。
内容的提问来源于stack exchange,提问作者Jaime
相关产品推荐
相关产品推荐

