初学者最痛苦的问题:
“我明明在函数里把 head 改了,为什么外面没变?”
答案就是:你只改了“副本”。
1)先用一句话说清:C 默认都是值传递
void f(int x){ x = 10; }外面变量不会变,因为x是拷贝。
指针也是一样:
void g(Node* head){ head = newHead; } // head 也是拷贝
2)什么时候必须用二级指针?
只要你想在函数里修改:
头指针
head自身
就必须用Node**
典型场景:
- 头插
- 删除头节点
- 初始化空链表(第一次插入)
- 清空链表(把 head 置 NULL)
3)用“头插”做对比,一眼就懂
❌ 错误:只传 Node*
void push_front_bad(Node* head, int x){ Node* n = create_node(x); n->next = head; head = n; // 只改了形参副本 }外面的head不会变。
✅ 正确:传 Node**
void push_front(Node** head, int x){ Node* n = create_node(x); n->next = *head; *head = n; // 改的是“外部 head 的地址指向的值” }4)二级指针到底是什么?
如果:
head是Node*(指向节点)那么
&head就是Node**(指向“指针变量 head”)
所以你传Node**本质就是:
把“指针变量本身”交给函数修改
5)极简 Demo(建议你复制运行)
#include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* next; } Node; Node* create_node(int x){ Node* n = (Node*)malloc(sizeof(Node)); n->data = x; n->next = NULL; return n; } void push_front_bad(Node* head, int x){ Node* n = create_node(x); n->next = head; head = n; } void push_front(Node** head, int x){ Node* n = create_node(x); n->next = *head; *head = n; } int main(){ Node* head = NULL; push_front_bad(head, 1); printf("after bad: %p\n", (void*)head); // NULL push_front(&head, 1); printf("after good: %p\n", (void*)head); // 非NULL return 0; }下一篇: 用 C 实现一个简化版 MessageQueue