二维数组指针重点在于指针定义和指针对地址的操作这两点上!
下面这个程序和程序下面的文字可以较好的体现
#include <stdio.h>
int main(){
int a[3][5] = { {0, 1, 2, 3,6}, {4, 5, 6, 7,8}, {8, 9, 10, 11,9} };
int (*p)[5];//此处不能去除括号!否则就不再是指向某个数组的【指针】
//而是变成一个存放指针的【数组】
//即*p[5]=*(p[5]),里面就只能存放5个指针
p=a;//把数组首地址a放入p中(a的地址就是a[0]的地址),所以等价于把a[0]的地址放入p
//上面两行最好合并为int (*p)[5]=a;
printf("*p[0] = %d\n",*p[0]);
printf("a=%p\n",a);//a=a[0]
printf("a[0]=%p, p=%p\n",a[0],p);//a[0]=p
printf("a[1]=%p, p+1=%p\n",a[1],p+1);//a[1]=p+1
printf("a[2]=%p, p+2=%p\n\n",a[2],p+2);
//p+1的实际地址操作为:p+sizeof(int)*5=p+20,即p+1实际上移动了20个地址位置
//因为p在定义时就为int,每一行就有5个int,所以p+1实际上移动了20个int大小
printf("sizeof(*(p+1))=%d\n\n", sizeof(*(p+1)));
//*(p+1)表示的是第一行的数据,即a[0]的所有数据
printf("a[1][1]=%d, *(p+1)[0]=%d\n", a[1][0],*(p+1)[0]);//所以*(p+1)==a[1]
printf("a[1][1]=%d, *(*(p+1)+1)=%d\n\n", a[1][1],*(*(p+1)+1));
//同理,因为*(p+1)==a[1],即*(p+1)是一个指针,那就可以通过指针的操作获得里面的数据
//即:*(*(p+1)+1)=a[1][1]
//*(p+1)+1外面的一个+1是指针移动了1个int大小
printf("sizeof(*(*(p+1)+1))=%d\n\n", sizeof(*(*(p+1)+1)));
return 0;
}
总体来说:int (* p)[5]=a;这一句的意思为:括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int,[5]表示p+1需要跳过5个int大小的地址,这正是 a 所包含的每个一维数组的类型。
而*(p+1)=a[1],这时*(p+1)+1就等价于a[1][a],即只移动一个int大小的地址!
输出为:
*p[0] = 0
a=0x7ffd1feb8f00
a[0]=0x7ffd1feb8f00, p=0x7ffd1feb8f00
a[1]=0x7ffd1feb8f14, p+1=0x7ffd1feb8f14
a[2]=0x7ffd1feb8f28, p+2=0x7ffd1feb8f28
sizeof(*(p+1))=20
a[1][1]=4, *(p+1)[0]=4
a[1][1]=5, *(*(p+1)+1)=5
sizeof(*(*(p+1)+1))=4