C语言 函数更改指针的地址

C语言中,通过函数更改指针的地址(即让指针指向一个新的地址)需要使用指向指针的指针。当一个指针作为函数参数传递时,函数仅获得了该指针的副本。因此,直接修改此副本不会影响原始指针指向的地址。要更改原始指针的地址,必须传递指向指针的指针(即双重指针)。

1、需要双重指针的原因

当我们希望在函数内部改变指针的指向时,如果仅传递指针本身,函数修改的只是这个指针的副本,对原始指针的值没有影响。使用双重指针,函数可以通过指向指针的指针访问和更改原始指针的地址,从而实现“改变指针的指向”。

1)使用单重指针无法更改指针地址

changePointer 函数使用的是单重指针 int *ptr。即使在函数中分配了新的内存地址并将 ptr 重新指向它,主函数中的 p 指针并没有发生变化,因为 changePointer 中的 ptr 只是 p 的一个副本。

#include <stdio.h>
#include <stdlib.h>

void changePointer(int *ptr) {
    ptr = (int *)malloc(sizeof(int)); // 试图修改指针的地址
    if (ptr != NULL) {
        *ptr = 10; // 赋值
    }
}

int main() {
    int *p = NULL;
    printf("Before changePointer: %p\n", (void*)p);

    changePointer(p);

    if (p != NULL) {
        printf("After changePointer: %p\n", (void*)p);
        printf("Value at new address: %d\n", *p);
    } else {
        printf("After changePointer: p is still NULL\n");
    }

    return 0;
}

2)使用双重指针更改指针地址

使用了双重指针 int **ptr。在 changePointer 函数中,我们改变了指针 p 的地址,使它指向了一块新分配的内存。主函数中的 p 被成功更新,并且新的地址生效了。

#include <stdio.h>
#include <stdlib.h>

void changePointer(int **ptr) {
    *ptr = (int *)malloc(sizeof(int)); // 修改了指针的地址
    if (*ptr != NULL) {
        **ptr = 10; // 赋值
    }
}

int main() {
    int *p = NULL;
    printf("Before changePointer: %p\n", (void*)p);

    changePointer(&p);

    if (p != NULL) {
        printf("After changePointer: %p\n", (void*)p);
        printf("Value at new address: %d\n", *p);
    }

    // 释放分配的内存
    free(p);

    return 0;
}

2、使用双重指针更改指针的地址

C语言中,函数中使用双重指针可以更改指针的地址,即让传入的指针变量指向一个新的地址。这种方法特别有用,例如在动态分配内存的场景中。当我们将一个指针传递给函数时,传递的是指针的副本,所以我们在函数内对指针赋值(更改地址)不会影响到原始指针。通过传入指针的地址(即双重指针),可以在函数中直接操作指针变量的地址,达到修改指针地址的目的。

#include <stdio.h>
#include <stdlib.h>

void allocateMemory(int **ptr) {
    *ptr = (int *)malloc(sizeof(int)); // 修改了指针的地址
    if (*ptr != NULL) {
        **ptr = 20; // 为新地址上的数据赋值
    }
}

int main() {
    int *p = NULL;
    printf("Before allocateMemory: p = %p\n", (void*)p);

    // 传递指针的地址,便于在函数中修改指针的地址
    allocateMemory(&p);

    if (p != NULL) {
        printf("After allocateMemory: p = %p\n", (void*)p);
        printf("Value at new address: %d\n", *p);
    }

    // 释放分配的内存
    free(p);

    return 0;
}

3、不使用双重指针的情况

如果直接传递指针,则无法更改原始指针的地址。修改的是指针的副本,对主函数中的 p 没有影响。

#include <stdio.h>
#include <stdlib.h>

void changePointer(int* ptr) {
    ptr = (int*)malloc(sizeof(int));  // 分配新内存,但不会影响原始指针
    if (ptr != NULL) {
        *ptr = 42;
    }
}

int main() {
    int* p = NULL;
    changePointer(p);  // 传递指针的副本

    if (p != NULL) {
        printf("New value: %d\n", *p);  // 不会执行,因为 p 仍然为 NULL
        free(p);
    } else {
        printf("Pointer is still NULL\n");  // 输出这行
    }

    return 0;
}

推荐阅读
cjavapy编程之路首页