数组指针
1.定义
数组指针是指向数组的指针,用来存放数组的地址。
2.数组指针与指针数组辨析
2.1指针数组
int* p1[10];
p1是指针数组。
下标引用[ ]的优先级高于间接访问*,p1先与[ ]结合为p1[10],是一个有10个元素的数组。其次再与 int *结合,即每个元素的类型是int *。
2.2数组指针
int (*p2)[10];
p2是数组指针。
虽然[ ]优先级高于*,但因为存在( )。p2先与 *结合,说明p2是一个指针变量。p2指向一个数组,该数组有10个int类型的变量。
p2的类型是:int (*)[10]
。 去掉变量名,即为数组指针的类型。
p2+1会跳过一个包含10个int类型元素的数组。
3.数组指针在一维数组上的示范:(很少用于一维数组)
int arr[]={1,2,3,4,5,6,7,8,9,10};
int (*p)[10]=&arr;
int sz=sizeof(arr)/sizeof(arr[0]);
int i=0;
for(i=0;i<sz;i++)
{
printf("%d ",*(*p+i));
}
分析:
p是数组指针,存放着数组arr的地址,指向数组arr。
*p标识了一个包含10个整型元素的数组arr。*p相当于数组名arr。我们知道数组名是数组首元素的地址,故 *p是数组arr首元素的地址,也是个指针。
这个可以验证:
p与*p中存放的地址的数值是一样的,但意义却大不一样。
p是数组arr的地址,所以p+1跳过了整个数组的字节大小。
根据图中打印出来的地址,我们可以看到:
数组地址+1减去数组地址,即16进制的90-68=28,转换成10进制就是40,刚好是一个有着10个int类型元素的数组的大小。
*p相当于数组名arr,是数组首元素的地址。所以 *p+1跳过了一个int类型。
根据图中打印出来的地址,我们可以看到:
数组首元素地址+1减去数组首元素地址,即16进制的6C-68=4。这是一个int类型值的大小。
再次强调一下(十分重要,最好能记住):
p是数组指针,存放着数组arr的地址,指向数组arr。
*p相当于(p所指的数组的)数组名arr, 所以 *p也是数组arr首元素的地址。
4.数组指针在二维数组上的应用
4.1写两个函数对比一下,一个用二维数组,一个用数组指针。
#include <stdio.h>
void print1(int arr[3][5],int row,int col);
void print2(int (*p)[5],int row,int col);
int main()
{
int arr[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};
print1(arr,3,5);
print2(arr,3,5);
return 0;
}
void print1(int arr[3][5],int row,int col)
{
int i=0;
for(i=0;i<row;i++)
{
int j=0;
for(j=0;j<col;j++)
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
void print2(int (*p)[5],int row,int col)
{
int i=0;
for(i=0;i<row;i++)
{
int j=0;
for(j=0;j<col;j++)
{
printf("%d ",*(*(p+i)+j));
}
printf("\n");
}
}
print1函数中规中矩,用二维数组数组名传参,用二维数组接收,不难理解。
print2函数的形式参数是数组指针,调用函数时的实际参数是二维数组的数组名arr。
我们知道二维数组的数组名是它第一行元素组成的一维数组的地址,简称为二维数组第一行的地址。它是一个数组的地址,所以可以用数组指针来接收。
4.2*(*(p+i)+j)
解析
下面的内容虽然看起来复杂,但只要抽丝剥茧,一步一步来即可。所有的知识点前面都已经提过。
p是一个数组指针,类型为
int (*p)[5]
。接收了二维数组的数组名arr,存放着二维数组第一行元素组成的一维数组的地址,也就是数组arr[0]的地址(如果这里困惑可以返回去看<3.二维数组的理解> 的内容)。
*p相当于第一行元素组成的数组的数组名arr[0],也是这个数组首元素的地址,即
arr[0][0]
的地址。
p+1跳过了二维数组一行的元素组成的数组的字节大小。
存放着第二行元素组成的数组的地址,即指向了二维数组的第二行。
p是二维数组第一行的地址;
p+i是二维数组第i行的地址;
*(p+i)是二维数组第i行元素组成的一维数组的数组名,也是第i行这个一维数组的首元素地址;
*(p+i)+j就是第i行第j列元素的地址。
4.3指针形式与数组形式的转化
4.3.1一维数组中
int arr[10]={0};
int* pa=arr;
int i=0;
for(i=0;i<10;i++)
{
printf("%p %p %p %p",&arr[i],(arr+i),(pa+i),pa[i]);
}
因为arr表示数组首元素的地址,此时指针变量与数组就建立了联系。
C语言在描述数组表示法时确实接助了指针。
定义arr[i]的意思就是*(arr+i),
*(arr+i)的意思是到内存的arr位置,然后移动i个单元,检索储存在那里的值。
所以这四个内容是等价的:
arr[i]
、*(arr+i)
、*(pa+i)
、pa[i]
4.3.2二维数组中
*(*(p+i)+j)
,
*(p+i)
可以写成p[i]
。
*(p[i]+j)
中p[i]存放着二维数组第i行首元素的地址,也是一个指针。故可以写成p[i][j]
。二者是等价的。
我们来验证一下:
欢迎大家和我沟通交流,对于相关的知识指出问题或提出建议,希望能和大家一起进步成长。