C语言传参疑问:单指针与双指针的适用场景是什么?
示例代码
// 基于链表实现队列的C语言示例 #include <stdio.h> #include <stdlib.h> struct QNode { int key; struct QNode* next; }; struct Queue { struct QNode *front, *rear; }; struct QNode* newNode(int k) { struct QNode* temp = (struct QNode*)malloc(sizeof(struct QNode)); temp->key = k; temp->next = NULL; return temp; } struct Queue* createQueue() { struct Queue* q = (struct Queue*)malloc(sizeof(struct Queue)); q->front = q->rear = NULL; return q; } void enQueue(struct Queue* q, int k) { struct QNode* temp = newNode(k); if (q->rear == NULL) { q->front = q->rear = temp; return; } q->rear->next = temp; q->rear = temp; } void deQueue(struct Queue* q) { if (q->front == NULL) return; struct QNode* temp = q->front; q->front = q->front->next; if (q->front == NULL) q->rear = NULL; free(temp); } int main() { struct Queue* q = createQueue(); enQueue(q, 10); enQueue(q, 20); deQueue(q); deQueue(q); enQueue(q, 30); enQueue(q, 40); enQueue(q, 50); deQueue(q); printf("Queue Front : %d \n", q->front->key); printf("Queue Rear : %d", q->rear->key); return 0; }
上述代码来自GeeksforGeeks网站。代码中函数调用时传入了指向结构体的指针,函数定义也接收指向结构体的指针,代码运行正常。我原本认为C语言是值传递,这类场景需要使用双指针才能修改实参,否则是值传递而非引用传递,对此存在疑惑,请问什么时候应该使用双指针,什么时候使用单指针即可?
解答
C语言确实只有值传递,不存在引用传递,你产生疑惑的核心原因是没有区分两种修改场景:修改指针指向的内存内容和修改指针本身存储的地址值。
为什么示例代码用单指针就可以正常运行
示例中enQueue和deQueue函数接收的struct Queue* q是形参,传参时会把main函数中实参q存储的地址值复制一份给形参q,此时两个q指向同一块struct Queue类型的内存空间。
函数内部修改的是这块内存空间里存储的front、rear成员的值,没有修改形参q本身存储的地址,所以哪怕是值传递,也能正常修改目标结构体的内容,不需要双指针。
什么时候需要用双指针
当你需要修改传入的指针变量本身存储的地址值时,就需要用双指针。因为如果只传单指针,函数拿到的是指针的副本,修改副本的地址不会影响外部实参指针,只有传指针的地址(也就是双指针),才能通过解引用修改外部实参指针本身的地址。
常见需要双指针的场景:
- 在函数内部给外部的指针变量分配内存
- 修改链表的头指针本身(比如删除头节点、头部插入节点)
- 需要修改外部传入的指针的指向时
简单判断规则
- 仅需要修改指针指向的内存中存储的内容,用单指针即可
- 需要修改指针变量本身存储的地址值,就需要传双指针
举个直观的对比示例:
// 场景1:修改指针指向的内容,单指针足够 void modify_value(int* p) { *p = 100; } // 场景2:修改指针本身的地址,需要双指针 void modify_pointer(int** p) { *p = malloc(sizeof(int)); **p = 200; } int main() { int a = 10; modify_value(&a); // 此时a的值变为100,符合预期 int* ptr = NULL; modify_pointer(&ptr); // 此时ptr不再是NULL,指向新分配的内存,存储的值为200 // 如果modify_pointer只用单指针,外部的ptr仍为NULL return 0; }
内容的提问来源于stack exchange,提问作者surya
相关产品推荐
相关产品推荐

