数组指针详解

数组指针

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]。二者是等价的。

我们来验证一下:
在这里插入图片描述
在这里插入图片描述

欢迎大家和我沟通交流,对于相关的知识指出问题或提出建议,希望能和大家一起进步成长。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值