记住很重要的一点:数组名=&数组名[0],比如,对于二维数组a[3][4] ,a等同于&a[0],a[0]等同于&a[0][0]
int main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *p1;
p1=a[0]; //表示数组a第一个元素的地址,相当于p1=&a[0][0]
//上面可以这么理解:对于一维数组a[],数组名a是第一个元素a[0]的地址,那么对于二维数组a[][],一维数组名a[0]是它的第一个元素a[0][0]的地址
p1=*a; //和上面的p1=a[0]是等同的,因为二维数组名a表示第一个一维数组a[0]的地址,则*a是表示第一个一维数组中的第一个元素即a[0][0]的地址
cout<<*p1<<endl; //输出a[0][0]
cout<<*(p1+1)<<endl; //输出a[0][1]
int (*p2)[4];
p2=&a[0]; //对整个一维数组a[0]求地址,此时p2是数组指针,指向4个int的一维数组
//此时p2是一维数组a[0]的首地址,虽然p2在数值上与&a[0][0]相等,但与&a[0][0]的意义完全不一样
p2=a; //和上面的p2=&a[0]是等同的,因为二维数组名a表示第一个一维数组a[0]的地址
cout<<*p2<<endl; //虽然加了取值符号,但此时*p2仍然是地址,表示所指向的a[0]的第一个元素的地址,即&a[0][0]
cout<<**p2<<endl; //输出a[0][0]
cout<<*p2+1<<endl; //表示所指向的a[0]的第二个元素的地址,即&a[0][1]
cout<<*(*p2+1)<<endl; //输出a[0][1]
cout<<p2+1<<endl; //因为p2是指向4个int的数组指针,所以指针+1会跳过4个int的地址,移动到下一个一维数组a[1]的首地址
//此时p2+1是一维数组a[1]的首地址,虽然p2+1在数值上与&a[1][0]相等,但与&a[1][0]的意义完全不一样
cout<<*(p2+1)<<endl; //表示所指向的a[1]的第一个元素的地址,即&a[1][0]
cout<<**(p2+1)<<endl; //输出a[1][0],即输出5
cout<<*(p2+1)+1<<endl; //表示所指向的a[1]的第一个元素的地址,即&a[1][1]
cout<<*(*(p2+1)+1)<<endl; //输出a[1][1],即输出6
int (*p3)[3][4];
p3=&a; //对整个二维数组a求地址,此时p3是数组指针,指向int [3][4]型数组
//虽然下面三句输出的内容一样,但它们表示的意义完全不一样
cout<<p3<<endl; //此时p3是二维数组a的首地址
cout<<*p3<<endl; //此时*p3表示a第一个一维数组的地址,即&a[0]
cout<<**p3<<endl; //此时**p3表示a第一个一维数组的第一个元素的地址,即&a[0][0]
cout<<***p3<<endl; //输出a[0][0]
cout<<p3+1<<endl; //因为p3是指向int [3][4]的数组指针,所以指针+1会跳过12个int的地址,移动到下一个二维数组的首地址
//因此,p3+1相当于二维数组a最后一个元素的下一个地址,即&a[2][3]+1
return 0;
}