C语言 数组的指针和指向数组的指针变量

一、回顾二维数组和多维数组的概念

int a[3][4];  //二维数组

int a[2][3]4];  //多维数组

二、指向多维数组的指针和指针变量的探究

可以把a看成是一个一维数组,这个一维数组有三个元素:a[0],a[1],a[2],每个元素又是一个包含4个元素的一维数组。

(1)a:二维数组名,也是整个二维数组的首地址。我们可以认为是第0行的首地址是1000

int a[3][4];   //数组名a,同样代表数组的首地址

int *p;

p=(int *)a;   //强制类型转换

(2)a+1,a+2 分别代表 第一行首地址 和第二行首地址。所以a+1跳过16个字节的,也就是a=1000,a+1=1016,a+2=1032

(3)这表示a[0],a[1],a[2]是一维数组名。C语言规定数组名代表数组的首地址,所以就有如下:

a[0] == &a[0][0]  == 1000  是第0行元素首地址

a[1] == &a[1][0]  == 1016  是第1行元素首地址

a[2] == &a[2][0]  == 1032  是第2行元素首地址

(4)第0行第1列元素地址怎么表示

&a[0][1] 等价于 a[0]+1   --> 1004

            

(5)推论:a[0] 等价于 *a;都是地址 1000   //a[0]==a[0][0],a是数组首地址

a[0]+1 等价于 (*a)+1   等价于 &a[0][1] ===> 1004

a[1]   等价于 *(a+1)   等价于 &a[1][0] ===>  1016

a[1]+2 等价于 *(a+1)+2 等价于 &a[1][2] ===> 1024

注意:这里不要把 *(a+1)+2 写成 *(a+3) 这样就变成了 a[3];

(6)a[0]+1 等价于 *a+1,等价于 &a[0][1],==> 1004,这是个地址。

   *(a[0]+1) 代表是 a[0][1] 的值;*(*a+1) 也是 a[0][1] 的值;

   *(a[1]+2) 代表是 a[1][2] 的值;*(*(a+1)+2) 也是 a[1][2] 的值;

(7)a[i]的性质问题

   a[i] 和 &a[i]地址值是一样的

实践:

#include<stdio.h>

int main()

{

    int a[3][4];

    int i,j;

    for(i=0;i<3;i++)

    {

        for(j=0;j<4;j++)

        {

            a[i][j]=86;  //给所有二维数组元素赋值为86

        }

    }

    int *p;

    p = (int *)(a+1);  //第一行首地址:a[1][0]--a[1][3]

    *p=56;           //a[1][0]=56;

    p++;             //走四个字节,到下一个数组元素

    *p=78;           //相当于a[1][1]=78

    printf("断点在这里\n");

    return 0;

}

三、指针数组和数组指针

1)指针数组:和普通指针变量一样,用来指向别的变量(保存变量的地址)

首先这是个数组,数组中有10个元素,每个元素都是个指针,所以这相当于定义了10个指针变量也就是p[0]-p[9]

int *p[10];   //相当于定义了10指针变量,能引用的下标是[0][9]

#include<stdio.h>

int main()

{

    int a[3][4];

    int i,j,k;

    for(i=0;i<3;i++)

    {

        for(j=0;j<4;j++)

        {

            a[i][j]=86;  //给所有二维数组元素赋值为86

        }

    }

    int *p[4];   //指针数组,能引用的下标是[0]--[3]

    p[0]=&a[0][0];

    p[1]=&a[0][1];

    p[2]=&a[0][2];

    p[3]=&a[0][3];

    for(k=0;k<4;k++)

        {

            printf("value=%d\n",*p[k]);

        }

    

    return 0;

}

2)数组指针:数组指针不太好理解,用的不多,熟悉概念就行【 数组指针的意思即为通过指针引用数组】

int (*p)[10];   //只定义了1个指针变量,这个指针变量是用来指向(保存) 含有10个元素的一维数组

例题1:

int main()

{

    int (*p)[10];

    int a[10]; //定义一个一维数组

    for(int i=0;i<10;i++)

    {

        a[i]=i;

    }

    p=&a;  //这里要用地址符&才行,&a 和a 的值相同

    int *q; //这里定义一个指针变量

    q=(int *)p;  //把数组指针保存的地址赋给q指针变量

    for(int j=0;j<10;j++)

    {

        printf("value=%d\n",*q);

        q++;

    }

    return 0;

}

数组的指针:是一个指针,指向数组的指针。

然后,需要明确一个优先级顺序:()>[]>*,所以:

(*p)[n]:根据优先级,先看括号内,则p是一个指针,这个指针指向一个一维数组,数组长度为n,这是“数组的指针”,即数组指针;

其次,对于语句“int(*p2)[5]”,“()”的优先级比“[]”高,“*”号和 p2 构成一个指针的定义,指针变量名为 p2,而 int 修饰的是数组的内容,即数组的每个元素。也就是说,p2 是一个指针,它指向一个包含 5 个 int 类型数据的数组,如图 2 所示。很显然,它是一个数组指针,数组在这里并没有名字,是个匿名数组。

由此可见,对指针数组来说,首先它是一个数组,数组的元素都是指针,也就是说该数组存储的是指针,数组占多少个字节由数组本身决定;而对数组指针来说,首先它是一个指针,它指向一个数组,也就是说它是指向数组的指针,在 32 位系统下永远占 4 字节,至于它指向的数组占多少字节,这个不能够确定,要看具体情况。

数组指针也称指向一维数组的指针,所以数组指针也称行指针。

最后,从上文来看:

     数组指针是一个指针变量,占有内存中一个指针的存储空间;

指针数组是多个指针变量,以数组的形式存储在内存中,占有多个指针的存储空间。

例题2:

例题3: 

例题4:

#include<stdio.h>

void print2(int (*p)[5],int x,int y)

{

    int i=0;

    for(i=0;i<x;i++)

    {

        int j=0;

        for(j=0;j<y;j++)

        {

            printf("%d ",*(*(p+i)+j));

            //p+i 表示二维数组的第几行一维数组的首地址。如:p+1是第二行一维数组{2,3,4,5,6}的首地址。

            //*(p+i)表示二维数组的第几行一维数组的数组名

            //(*(p+i)+j)表示二维数组的一维数组中的第几个元素的地址,数组名就是数组首地址。如:(*(p+1)+1)是第二行一维数组{2,3,4,5,6}元素3的地址

            //*(*(p+i)+j)表示二维数组的一维数组中的第几个元素。如:*(*(p+1)+2)==4.

        }

        printf("\n");

    }

}

int main()

{

    int arr[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};

    print2(arr,3,5);

    return 0;

}

四、多维数组的指针做函数参数

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值