目录
区分概念:数组指针和指针数组
数组指针:是指向一个数组的首地址的指针,其本质为指针。如:int (*p)[5]
指针数组:由若干个具有相同储存类型和数据类型的指针变量构成的集合,本质是是数组。 如:int *p[5]
1.指针和一维数组
1.1一维数组元素的表示
当用指针指向一维数组的首地址后,一维数组的元素表示方法就有很多了,来看下面一段代码:
int s[5]={1,2,3,4,5};
int *p1=s;
//int *p2 = &s[0]; //这样也可以写
需要知道的是,指针的一次相加是以定义指针的数据宽度为单位的,而不是以字节位单位,也就是说当指针类型和指向的一维数组为同一类型时,指针+1指向的是数组的下一个元素。
printf("s[0]=%d ",s[0]);
printf("*p1=%d ",*p1);
printf("s[1]=%d ",s[1]);
printf("*(p1+1)=%d ",*(p1+1));
printf("*(s+1)=%d ",*(s+1));
输出的结果为:
由此得出结论:表示一维数组s的第i个元素,有下标法和指针法。假设指针变量指向数组中的首元素,则有四种表达方式,s[i]<=>p[i]<=>*(p+i)<=>*(a+i)
指针和数组常见的等价操作如下:
指针操作 | 数组操作 | 说明 |
array | &array[0] | 元素首地址 |
*array | array[0] | 数组的首元素 |
array+i | &array[i] | 数组第i个元素的地址 |
*(array+i) | array[i] | 数组的第i个元素 |
*array+b | array[0]+b | 数组首元素的值加b |
*(array+i)+b | array[i]+b | 数组第i个元素的值加b |
*array++(当前指向第i个元素) | array[i++] | 先取得第i个元素的值,i再加1 |
*++array(当前指向第i个元素) | array[++i] | 先将i加1,再取得第i个元素的值 |
*array--(当前指向第i个元素) | array[i--] | 先取得第i个元素的值,i再减1 |
*--array(当前指向第i个元素) | array[--i] | 先将i减1,再取得第i个元素的值 |
1.2一维数组的遍历
紧接上面的代码:
int len=0,i;
len=sizeof(s)/sizeof(int);
for(i=0;i<len;i++)
{
printf("%d %d %d %d\n",s[i],p1[i],*(s+i),*(p1+i));
}
输出的结果为:
2.指针和二维数组
首先要知道二维数组再内存中的储存形式:二维数组的元素连续存储,按行优先存储,存储了第一行的元素,存储第二行的,以此类推。
2.1二维数组元素的表示
在没用用指针指向二维数组之前,二维数组元素的表示方法有:s[i][j]、 *(*(s+i)+j)、*(s[i]+j)
int s[3][3] = { {11,22,33},{44,55,66},{77,88,99} };
printf("**s=%d ", **s);
printf("*(*s+1)=%d ", *(*s + 1));//相当于*( * (s + 0) + 1)
printf("s[1][1]=%d ", s[1][1]);
printf("*(*(s+1)+1)=%d ", *( * (s + 1) + 1));
printf("*(s[1]+1)=%d ", *(s[1] + 1));
因为二维数组的数组名是行地址,对行指针取一个*操作,相当于对指针的降维,把操作空间是一整行的指针降维成操作空间是一个元素的指针,再取一次*操作,就可以读取到数据了。上述代码的运算结果为:
由此可见s[i][j]<=> *(*(s+i)+j) <=>*(s[i]+j)
当我们用指针指向二维数组时,二维数组元素的表示方法又多了很多。二维数组名为行地址,因此我们不能用一个普通的指针变量来指向二维数组,即使指向了也只能按照单个元素来操作,不能按照整行来操作,因此我们需要用到数组指针,来看下面一段代码:
int s[3][3] = { {11,22,33},{44,55,66},{77,88,99} };
int (*p)[3] = s;
printf("**p=%d ", **p);
printf("*(*p+1)=%d ", *(*p + 1));//相当于*( * (p + 0) + 1)
printf("p[1][1]=%d ", p[1][1]);
printf("*(*(p+1)+1)=%d ", *( * (p + 1) + 1));
printf("*(p[1]+1)=%d ", *(p[1] + 1));
代码的运行结果:
也就是说p[i][j]<=> *(*(p+i)+j) <=>*(p[i]+j)
联想到上面不难发现s[i][j]<=> *(*(s+i)+j) <=>*(s[i]+j)<=>p[i][j]<=> *(*(p+i)+j) <=>*(p[i]+j)
2.2二维数组的遍历
基于上述,遍历的代码不难写:
int i, j, r, c;
r = sizeof(s) / sizeof(s[0]);
c = sizeof(s[0]) / sizeof(int);
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("%d %d %d", s[i][j], *(*(s + i) + j), *(s[i] + j));
printf(" %d %d %d", p[i][j], *(*(p + i) + j), *(p[i] + j));
printf("\n");
}
}
代码的运行结果如下: