034. 理解指针的指针

在C语言中,指针的指针(即指向指针的指针)是一个高级概念,它允许你处理更复杂的数据结构,如二维数组、动态分配的矩阵、链表等。理解指针的指针对于掌握C语言的高级特性非常重要。以下将通过具体示例详细解释指针的指针的使用。

1. 定义指针的指针

指针的指针是一个指针,它指向另一个指针。定义指针的指针时,需要使用两个*

示例1:定义指针的指针

#include <stdio.h>

int main() {
    int value = 10; // 定义一个整数变量
    int *ptr = &value; // 定义一个指向整数的指针
    int **ptrPtr = &ptr; // 定义一个指向指针的指针

    printf("Value: %d\n", value); // 输出变量的值
    printf("Value via ptr: %d\n", *ptr); // 通过指针访问变量的值
    printf("Value via ptrPtr: %d\n", **ptrPtr); // 通过指针的指针访问变量的值

    return 0;
}

输出结果

Value: 10
Value via ptr: 10
Value via ptrPtr: 10

2. 修改变量的值

可以通过指针的指针修改变量的值。

示例2:通过指针的指针修改变量的值

#include <stdio.h>

int main() {
    int value = 10; // 定义一个整数变量
    int *ptr = &value; // 定义一个指向整数的指针
    int **ptrPtr = &ptr; // 定义一个指向指针的指针

    printf("Original value: %d\n", value); // 输出原始值

    **ptrPtr = 20; // 通过指针的指针修改变量的值

    printf("Modified value: %d\n", value); // 输出修改后的值

    return 0;
}

输出结果

Original value: 10
Modified value: 20

3. 指针的指针与二维数组

指针的指针常用于处理二维数组。二维数组可以看作是一个指针数组,每个指针指向一个一维数组。

示例3:使用指针的指针处理二维数组

#include <stdio.h>

int main() {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    int rows = 3, cols = 4;
    int (*ptr)[4] = matrix; // 定义一个指向二维数组的指针

    // 使用指针的指针访问二维数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("Element at [%d][%d]: %d\n", i, j, *(*(ptr + i) + j));
        }
    }

    return 0;
}

输出结果

Element at [0][0]: 1
Element at [0][1]: 2
Element at [0][2]: 3
Element at [0][3]: 4
Element at [1][0]: 5
Element at [1][1]: 6
Element at [1][2]: 7
Element at [1][3]: 8
Element at [2][0]: 9
Element at [2][1]: 10
Element at [2][2]: 11
Element at [2][3]: 12

4. 动态分配二维数组

指针的指针也可以用于动态分配二维数组。动态分配的二维数组可以更灵活地处理不同大小的数组。

示例4:动态分配二维数组

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

int main() {
    int rows = 3, cols = 4;
    int **matrix = (int **)malloc(rows * sizeof(int *)); // 分配行指针

    for (int i = 0; i < rows; i++) {
        matrix[i] = (int *)malloc(cols * sizeof(int)); // 分配每行的列
    }

    // 初始化二维数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j + 1;
        }
    }

    // 打印二维数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    // 释放动态分配的内存
    for (int i = 0; i < rows; i++) {
        free(matrix[i]);
    }
    free(matrix);

    return 0;
}

输出结果

1 2 3 4 
5 6 7 8 
9 10 11 12 

5. 指针的指针与函数参数

指针的指针可以作为函数参数,用于修改指针指向的地址。这在实现动态分配或修改指针时非常有用。

示例5:使用指针的指针作为函数参数

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

// 函数:动态分配一个整数数组
void allocateArray(int **arr, int size) {
    *arr = (int *)malloc(size * sizeof(int));
    if (*arr == NULL) {
        printf("Memory allocation failed\n");
        exit(1);
    }
}

// 函数:释放动态分配的数组
void freeArray(int *arr) {
    free(arr);
}

int main() {
    int *array;
    int size = 5;

    // 动态分配数组
    allocateArray(&array, size);

    // 初始化数组
    for (int i = 0; i < size; i++) {
        array[i] = i + 1;
    }

    // 打印数组
    for (int i = 0; i < size; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");

    // 释放动态分配的数组
    freeArray(array);

    return 0;
}

输出结果

1 2 3 4 5

通过上述示例,你可以看到指针的指针在C语言中的多种用途:

  1. 定义指针的指针:使用两个*定义指针的指针。
  2. 通过指针的指针访问和修改变量的值:使用**访问和修改变量的值。
  3. 处理二维数组:指针的指针可以用于处理二维数组。
  4. 动态分配二维数组:指针的指针可以用于动态分配和管理二维数组。
  5. 作为函数参数:指针的指针可以作为函数参数,用于修改指针指向的地址。

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)