C语言二维数组指针的指针的指针怎么定义?

99ANYc3cd6
预计阅读时长 18 分钟
位置: 首页 C语言 正文

从简单到复杂

为了理解 int ***ppp,我们最好从最基础的开始,一步步构建起来。

c语言定义二维数组指针的指针的指针
(图片来源网络,侵删)

一维数组

一个普通的一维数组:

int arr[5] = {1, 2, 3, 4, 5};
  • arr 是一个包含 5 个 int 类型元素的数组。
  • &arr[0] 是数组第一个元素的地址,其类型是 int *
  • int *p = arr; 定义了一个指向 int 的指针 p,它可以指向 arr 中的任何一个元素。

二维数组

一个普通的二维数组:

int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};
  • matrix 是一个包含 3 个元素的数组,这 3 个元素本身都一个包含 4 个 int 类型元素的数组。
  • matrix[0] 是第一行,它本身是一个包含 4 个 int 的数组。&matrix[0] 是第一行的地址。
  • &matrix[0] 的类型是什么?它是一个指向“包含 4 个 int 的数组”的指针,类型是 int (*)[4],我们称之为“数组指针”。
  • int (*p_matrix)[4] = matrix; 定义了一个数组指针 p_matrix,它可以指向 matrix 的任意一行。

指针的指针 (Pointer to a Pointer) - int **

int ** 是一个指向“指向 int 的指针”的指针,它通常用于表示一个动态的、不规则的二维数组(即数组的每一行长度可以不同),或者更常见地,表示一个字符串数组char **)。

int *row1 = malloc(4 * sizeof(int));
int *row2 = malloc(4 * sizeof(int));
// ...
int **dynamic_matrix = malloc(3 * sizeof(int *));
dynamic_matrix[0] = row1;
dynamic_matrix[1] = row2;
// ...
  • dynamic_matrix 是一个 int ** 类型的变量。
  • dynamic_matrix 指向一个 int * 类型的指针(row1 的地址)。
  • *dynamic_matrix (即 dynamic_matrix[0]) 本身是一个 int *,它指向 row1 数组的第一个元素。
  • **dynamic_matrix (即 dynamic_matrix[0][0]) 是一个 int,即 row1 的第一个元素的值。

目标:指针的指针的指针 - int ***

我们终于可以理解 int *** 了。

c语言定义二维数组指针的指针的指针
(图片来源网络,侵删)

int *** 是一个指向“指向 int 的指针的指针”的指针。

  • ***ppp 最终解引用到一个 int 类型的值。
  • **ppp 是一个 int * 类型(指向 int 的指针)。
  • *ppp 是一个 int ** 类型(指向 int * 的指针)。
  • ppp 是一个 int *** 类型(指向 int ** 的指针)。

定义与使用示例

int ***ppp 这种结构通常用于处理三维数据,或者更常见地,用于动态分配和传递一个不规则的二维数组(`int `)的指针**。

让我们来看一个完整的例子,这个例子将动态分配一个二维数组,然后使用 int *** 来修改这个二维数组的“行指针”本身。

示例代码

#include <stdio.h>
#include <stdlib.h>
// 函数声明
void allocate_and_init_2d_array(int ***ppp, int rows, int cols);
void print_2d_array(int **matrix, int rows, int cols);
void free_2d_array(int **matrix, int rows);
int main() {
    int rows = 3;
    int cols = 4;
    int **my_matrix = NULL; // 初始化为 NULL
    // 1. 分配二维数组,并让 my_matrix 指向它
    //    我们将 my_matrix 的地址传递给函数,这样函数内部就可以修改 my_matrix 本身
    allocate_and_init_2d_array(&my_matrix, rows, cols);
    // 2. 打印二维数组
    printf("The 2D array after allocation:\n");
    print_2d_array(my_matrix, rows, cols);
    // 3. 释放二维数组
    free_2d_array(my_matrix, rows);
    return 0;
}
/**
 * @brief 动态分配一个 rows x cols 的二维数组,并通过指针的指针的指针来返回它。
 * 
 * @param ppp 一个指向 "int **" (即二维数组指针) 的指针。
 *            也就是 my_matrix 的地址。
 * @param rows 行数
 * @param cols 列数
 */
void allocate_and_init_2d_array(int ***ppp, int rows, int cols) {
    // *ppp 等价于 main 函数中的 my_matrix
    // *ppp = ... 的意思是 my_matrix = ...
    *ppp = (int **)malloc(rows * sizeof(int *));
    if (*ppp == NULL) {
        fprintf(stderr, "Memory allocation failed for rows.\n");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < rows; i++) {
        // 解引用 *ppp 得到 my_matrix,my_matrix[i] 就是分配每一行的内存
        (*ppp)[i] = (int *)malloc(cols * sizeof(int));
        if ((*ppp)[i] == NULL) {
            fprintf(stderr, "Memory allocation failed for columns in row %d.\n", i);
            exit(EXIT_FAILURE);
        }
        // 初始化数据
        for (int j = 0; j < cols; j++) {
            // (*ppp)[i][j] 等价于 my_matrix[i][j]
            (*ppp)[i][j] = i * cols + j + 1;
        }
    }
}
/**
 * @brief 打印一个二维数组
 */
void print_2d_array(int **matrix, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%3d ", matrix[i][j]);
        }
        printf("\n");
    }
}
/**
 * @brief 释放一个动态分配的二维数组
 */
void free_2d_array(int **matrix, int rows) {
    for (int i = 0; i < rows; i++) {
        // 先释放每一行的内存
        free(matrix[i]);
    }
    // 再释放存放行指针的数组
    free(matrix);
    printf("\n2D array freed successfully.\n");
}

代码解析

  1. main 函数:

    c语言定义二维数组指针的指针的指针
    (图片来源网络,侵删)
    • int **my_matrix = NULL; 我们定义了一个 int ** 类型的指针,并初始化为 NULL,这个指针将最终指向我们动态分配的二维数组。
    • allocate_and_init_2d_array(&my_matrix, rows, cols); 关键点在这里!我们传递的不是 my_matrix,而是 &my_matrixmy_matrix 的地址)。
  2. allocate_and_init_2d_array 函数:

    • 函数参数是 int ***ppp,这意味着 ppp 是一个指向 int ** 的指针。
    • main 函数中,我们传递了 &my_matrix,在 allocate_and_init_2d_array 内部,ppp 就指向了 main 函数中的 my_matrix 变量。
    • *ppp 通过解引用,就得到了 main 函数中的 my_matrix 本身,它的类型是 int **
    • *ppp = (int **)malloc(...) 这行代码的含义是:修改 main 函数中 my_matrix 的值,让它指向新分配的内存块(这个内存块里存放的是指向每一行的指针)。
    • (*ppp)[i] = ... 这里的括号是必须的。*ppp 的优先级低于 [](*ppp)[i] 表示“先解 ppp 得到 my_matrix,然后访问 my_matrix 的第 i 个元素”,这等价于 my_matrix[i]

int *** 的用途

指针类型 含义 常见用途
int ***ppp 指向“指向 int 的指针的指针”的指针 动态三维数组int *** 指向一个 int ** 数组,每个 int * 指向一个 int 数组)。
修改一个二维数组指针(`int )本身**,当你需要在一个函数内部分配一个二维数组,并让调用者的指针变量指向这个新分配的数组时,就需要传递int ***`。

理解 int *** 的关键在于从里向外逐层解引用,并始终记住每一层指针的类型,虽然看起来复杂,但只要掌握了 int *int ** 的逻辑,int *** 也就水到渠成了。

-- 展开阅读全文 --
头像
页自定义图片字段怎么用?
« 上一篇 2025-12-14
从问题到程序,如何设计C语言?
下一篇 » 2025-12-14

相关文章

取消
微信二维码
支付宝二维码

目录[+]