int a[3][4];
int **p;
如上是一个二维数组和一个双重指针,在普遍情况大多数人认为二维数组名a是可用一个双重指针来指向的,但是实际情况中这么做无法通过编译器。
为了弄清这么个问题,我们对二维数组和双重指针做一次分析。
int a[3][4];
对于二维数组a我们要知道其原理,二维数组a是一个包含了3个元素的一维数组,这三个元素每一个都是包含了4个整型元素的一维数组,也即二维数组a是一个元素为一维数组的一维数组。
那么数组名a, a[0], &a[0][0]
分别代表什么呢?如下图
图中分别打印出a, a[0], &a[0][0], a+1, a[1], &a[1][0], a[0]+1, &a[0][1]
的值。
在理解二维数组过程中,我们可以将其当做一个一维数组来看,只是这个一维数组中的每个元素也是一维数组而已。
我们知道一维数组名为其首个元素的地址,也就是说,二维数组名a为首个元素的地址,也就是首行一维数组的地址。a[0]为首个元素,也就是首行数组名,其也为地址。
观察运算结果得出结论:
a
为首行地址a[0]
为首行首个元素的地址&a[0][0]
为整个数组首个元素的地址以上三者地址完全相同,但是意义不同。
a + 1
为第二行数组的地址,加1就是往后偏移一位a[1]
为第二行数组首个元素的地址&a[1][0]
等同于2另外a[0] + 1
也与&a[0][1]
是等同的,均为首行第二个元素的地址。
双重指针就是指向指针的指针,想了解更多可以看下面这个博客。
双重指针的理解
回到最初得问题,为什么双重指针不能指向二维数组呢?
分析:二维数组名a本身也只是一个一维指针,其指向是一整个数组,而双重指针是指向指针的指针,与指向数组的指针是不能完全等价的,所以编译器不让通过。
所以想要指向一个二维数组,我们就可以定义一个指向数组的指针来指向它,即
这样编译器就不会报错。
int (*p)[4];
是一个指针数组,首先p是一个指针,然后其指向一个包含四个元素的数组,这四个元素均为整型。阅读这样的定义要记住从内向外阅读,再从右向左绑定修饰符。
指针数组和数组指针
指针数组:int (* p)[10]; //p指向一个包含10个整数的数组
数组指针:int *p[10]; //p是一个数组,每个元素都是一个指向一个整数的指针
另外也可用数组的类型别名来指向二维数组
数组的类型别名
using int_array = int[4];
等价于 typedef int int_array[4];
其中数据类型int_array表示一个包含4个整数的数组类型。
int_array p; //p为一个包含4个整数的一维数组
对二维数组a,有int_array *p = a; //p指向a中第一个包含4个元素的一维数组,p++则*p为a中第二行的数组
暂且记录在此,如有纰漏或错误,敬请批正。