C++ 二级指针与二维数组

本文最后更新于:2023年11月12日 下午

前情提要

1
2
int a[2][3] = { 1,2,3,4,5,6 };
int** ptr = (int**)a;

把二维数组赋值给二级指针,该如何通过ptr对第i行第j列进行访问呢?

有人说,简单:ptr[i][j]

那么好,众所周知:ptr[i][j] == *(*(ptr+i)+j) //编译器展开

那么ptr + i 的步长是多少,或者说ptr + 1 移动了几个字节

那么显然是移动【指针指向的元素的大小】,也就是int* 的大小

那么显然:ptr[i][j] 不能正确定位第i行第j列

其实,int** ptr = a;就会发出警告 "int(*)[3]"类型的值不能用于初始化"int**"类型的实体 也许,这说明,数组只能退化为一级指针

如果在这种情况下,想要强行通过ptr访问

只能:*((int*)ptr + i * N + j) 强转为一级指针 //N是一行的元素个数

注意

同时,**ptr 会直接造成越界访问

这是因为第一次解引用*ptr 其实就已经是第一个元素的值1 了 //32位系统下

也就是说,(int)(*ptr) == 1 //32位系统下

而且,解引用意味着找到指针所存地址上的值

如果把第一个元素看做指针,那么该指针所存的地址是1吗?不一定

  • 32位系统下,指针是4个字节
  • 64位系统下,指针是8个字节,那么第一第二个元素会被共同解释为地址

然后会去该地址(比如0000000200000001)寻找值

那么显然越界访问了,直接bomb,异常

Solution

所以,方法1:int (*ptr)[3] = a;

众所周知:右左法则(注意括号),跟我读:ptr是一个指针(*),指向一个数组([3]),这个数组有3个元素,元素类型是int

恒河里

所以,a[2][3]实际上就是有两个这样的一维数组[3],数组的数组

酱紫的话,ptr++,就可以在这两个一维数组的首地址跳跃了,步长为int[3]

所以也可以ptr[i][j]进行访问

方法2:int** ptr = new int*[N];

这将意味着,申请的空间是一个一维数组,数组的每一个元素都是int* 类型

这种情况下,每一个int*都会指向一个一维数组

所以ptr[i]就是第i个一维数组的首地址,ptr[i][j]就是这个数组的第j个元素

所以可以正常访问

就是需要循环申请内存

1
2
3
4
int** ptr = new int*[rows];
for (int i = 0; i < rows; i++) {
ptr[i] = new int[cols];
}

Peace


C++ 二级指针与二维数组
https://mrbeancpp.github.io/2023/11/11/C-二级指针与二维数组/
作者
MrBeanC
发布于
2023年11月11日
许可协议