看这个标题都要晕了,我们不妨把他拆开来理解,比较容易
指针数组:对象是一个数组,数组元素的类型是指针
指针数组的定义方式:
类型名 *数组名[数组长度];
如:
int *p[8];
数组指针:对象是一个指针,指针的类型是一个数组
数组指针的定义方式:
类型名 (*数组名)[数组长度];
如:
int (*p)[8];
无论是使用指针数组或是数组指针,都可以达到我们想要的效果,
下面我们就来比较一下两种对象操作数组的方式:
#include <stdio.h> void main(int argc,char *argv[]) { int arr[4][4]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; int (*p1)[4]; int *p2[4]; int i,j,k; p1=arr; printf("使用数组指针的方式访问二维数组arr "); for(i=0;i<4;i++) { for(j=0;j<4;j++) { printf("arr[%d][%d]=%d ",i,j,*(*(p1+i)+j)); } printf(" "); } printf(" 使用指针数组的方式访问二维数组arr "); for(k=0;k<4;k++) p2[k]=arr[k]; for(i=0;i<4;i++) { for(j=0;j<4;j++) { printf("arr[%d][%d]=%d ",i,j,*(p2[i]+j)); } printf(" "); } return ; }
输出结果都是0-15,说明访问方式都是正确的,下面我们来分析一下 数组指针 的访问元素的方式:
访问方式: *(*(p1+i)+j)
根据运算符优先级,将这个运算过程拆开来分析
(p1+i) -> *(p1+i) -> *(p1+i) +j-> *(*(p1+i)+j)
我们将它分为四个部分:
1. p1是指向数组的指针,数组的长度是4,也就是说,p1+1的话,内存地址实际是加了4(32位系统)位,这样的话,
使用(p1+i)就可以找到数组中每个元素的地址
2. 使用取值运算将第一步的运算结果取值,开始我在这里疑惑了好久,开始我认为 *(p1+1) 的结果是等于4,对地址进行取值嘛,理所应当,
然而结果并不是这样,*(p1+i)的结果是仍然是一个指针,为什么呢,因为我们的数组元素也是一个数组,也就是说,我们使用p1+i得到的也是一个数组指针,这样就理解通了吧,
*(p1+i)得到的是二层数组的首地址
3.得到了二层数组的首地址之后,我们再加上偏移量i,就得到数据在数组中的地址了
4.得到了数据地址,使用取值符就可以得到真实数据了
看懂了数组指针,指针数组也就迎刃而解了