You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:24:06