int **p 是什么?一文读懂二级指针与二维数组

好问题!这其实是 C 语言里指针基础中的进阶用法int **p 是一个指向指针的指针,也称为“二级指针”或“指针的指针”。我们来系统地讲清楚这个用法。

int **p 是什么?

 int **p;

含义:p 是一个指针,它指向另一个指向 int 类型的指针。

换句话说:

  • int 是数据

  • int * 是指向整数的指针

  • int ** 是指向“指向整数的指针”的指针

图解(模拟内存结构)

 int a = 10;
 int *p1 = &a;
 int **p2 = &p1;

结构图像这样

 a     = 10
 &p1   = 地址1
 p1   = &a     ---> 指向 a 的地址
 &p2   = 地址2
 p2   = &p1     ---> 指向 p1 的地址
 
 *p2   = p1     ---> 解引用一次,得到 p1
 **p2 = *p1     ---> 解引用两次,得到 a

所以:

  • *p2 == 10

  • p2 == p1

  • p2 == &p1

示例代码演示

 #include <stdio.h>
 
 int main() {
     int a = 42;
     int *p1 = &a;
     int **p2 = &p1;
 
     printf("a = %d\\n", a);
     printf("*p1 = %d\\n", *p1);
     printf("**p2 = %d\\n", **p2);
 
     return 0;
 }

输出:

 a = 42
 *p1 = 42
 **p2 = 42

二级指针常见应用场景

应用场景举例
修改指针的值(比如函数里改变传入指针)void modify(int **pp)
传递二维数组(模拟 int[][]int **matrix
命令行参数 main(int argc, char **argv)字符串指针数组
动态创建字符串数组或 int 数组的数组动态内存管理时用

示例:通过函数修改指针值

 void set_ptr(int **pp) {
     static int val = 999;
     *pp = &val;
 }
 int main() {
     int *p = NULL;
     set_ptr(&p);
     printf("*p = %d\\n", *p);  // 输出 999
 }

总结一张表

声明含义指向
int a普通整型存储一个整数
int *p指针变量指向一个整数
int **pp二级指针指向一个“指向整数”的指针

二阶指针和二维数组

二维数组(2D Array)

 int arr[3][4];  // 一个3行4列的二维整型数组
 int **p;  // 一个指向 int 指针的指针

可以用来动态创建二维结构,但内存是分散的

内存结构

二维数组:

 int arr[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
 };

在内存中是连续的:

1 2 3 4 5 6(按行优先顺序排列)

二阶指针模拟二维数组:

 int **p = malloc(rows * sizeof(int *));
 for (int i = 0; i < rows; ++i)
     p[i] = malloc(cols * sizeof(int));

每一行是单独分配的,每一行的地址可能不连续

使用方式比较

操作二维数组二阶指针
声明方式int arr[3][4]int **p
内存分配编译时固定运行时动态分配
内存结构连续分散(非连续)
访问方式arr[i][j]p[i][j]
可变大小否(除非用变长数组)是,适合动态数组

使用场景

  • 二维数组:适合大小固定、效率优先、栈上分配的场景。

  • 二阶指针:适合动态创建二维结构(如动态输入表格),但管理起来更复杂(需手动释放每一行内存)。

注意事项

  • 不要把 int arr[3][4] 当成 int ** 来用,它们底层结构不一样,不能强转。

  • 如果需要传递二维数组给函数,声明应为:

     void func(int arr[][4])  // 或 func(int (*arr)[4])

    对于二阶指针则:

     void func(int **p)

إرسال تعليق

أحدث أقدم