C++ 二级指针与二维数组
本文最后更新于:2023年11月12日 下午
前情提要
1 | |
把二维数组赋值给二级指针,该如何通过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 | |