首先已知数组int a[5][2]={0,1,2,3,4,5,6,7,8,9};按照地址连续性a[0][0],a[0][1],a[1][0],a[1][1],a[2][0].......按对应顺序赋值。
对比两行代码:
int *p=a[0];
int (*p2)[2] = &a[1];
一、p是一个int型的指针,指向一个int型地址,类型为int *。
p2是一个指向维度2大小的int数组的指针,类型为int(*)[2]。
对p取值,*p是一个值,在这个代码中对应a数组第一行第一列的元素值0。
对p2取值,*p2是一个指针,表示指向数组的首地址,**p2才是首地址的值,在这个代码中对应第二行第一个元素值1
同时,p和p2的自增跨度也不一样,p自增是一个int型长度,p2自增是int[2]长度,因此,如执行p++,p2++;之后。再对分别取值printf("p1=%d,p2=%d",*p,**p2);,那么*p就变成第一行第二个元素值1,而**p2就变成第三行第一个元素值4(原本是第二行第一个元素值)。
二、搞清楚p和p2的区别,剩下的就是赋值对应类型了。二维数组a,a[0]表示第一行的行指针,是int*类型,自然赋值给p,不需要加&。而上面说了*p2取值是一个指针,所以给p2赋值需要一个指针的地址,所以&a[1]要加&符号取地址。
PS:a作为数组名是一个指针常量,它的类型就是int(*)[2],表示指向第一行的行指针的地址。所以可以直接赋值p2=a;。