数组 指针杂记

  1. 一维数组

    一维数组例如:int a[5]={0};

    数组实际上是一种构造类型,是内存的一段连续的存储区域。

    其中int指明了内存访问方式,包括元素的类型,每次跳跃的步长;

    其中5指明了构造类型中数据元素的个数,也就是说指明了数组访问时候的可偏移的范围;

    其中a有两重含义:

    1).作为数组名,a表示一种构造数据类型,这也就是为什么 sizeof(name) == sizeof(type [N])。

    2).作为数组名,访问成员时它是首元素的地址 name[i] == *(name+i) == i[name]。

    其中{0},表示部分初始化,这样写代表把第一个元素初始化为0,当我们部分初始化时候,没有被我们初始化的元素自动初始化为0,而不是说我们{0}就把全部的元素初始化为0,若是{10},也就是第一个元素10,其他元素自动为0.

    对于数组可做如下理解:

    类型:type [N]

    定义:type name[N]

    大小:sizeof(type [N]) 或 sizeof(name)

    但是当我们 做这样的定义:int *p=name;或者把数组作为参数传递到函数中时,这个时候再求sizeof(p)的大小就仅仅是当前系统下一个指针类型的大小了(32位系统指针类型大小为4个字节,64为系统指针类型为8个字节)。若是在数组定义的区域内对数组名求sizeof()的到的就是整个数组在内存中所占空间大小。

    为什么非要是a[0]开始呢?[ ]可以理解为基址变址运算符,对于a[0]来说,a是基址,0是偏移量,合起来就是变址,a[0]等价于*(a+0),由于a代表首元素的地址,所以只有当a偏移0个单位才可以访问到首元素,所以必须是a[0]开始。基于以上原理,其实 a[i] 可以写成 i[a],它依然等价于*(a+i)。

    C语言不允许数组越界,但是自己不做越界检查,要程序员自己做越界检查,所以要是访问越界,那结果将是没有定义的,会造成不可预知的错误。

    一维数组名,本质上是一个一级指针,但是对一维数组名做 & 运算,得到的是一个数组指针,而不是一个二级指针。

    int array[10];

    int (*p)[10]=&array;//这是正确的

    int **p=&array;//这是错误的

    可以通过一级指针修改0级指针的内容,可通过N级指针修改N-1级指针的指向,总结起来还是一句话,通过指针可以修改它所指向的内容。

    下面是一下大小还有跳跃幅度的大小比较程序:

  2. #include <stdio.h>
    int main(void)
    {
        //对于一个普通的int型变量
        int a;
        printf("&a=%p\n",&a);
        printf("&a+1=%p\n",&a+1);
        int *p = NULL;
        printf("p = %p p +1 = %p\n",p,p+1);
        /*
         * &a+1比&a大4,原因是&a是一个int *类型,每次跳跃步长是4个字节,
         * 相应的一个char类型的则每次跳跃1个字节
        */
        int array[10];
        printf("array = %p\n",array);
        printf("array +1 = %p\n",array+1);
        /*后者比前者大4*/
        printf("&array = %p\n",&array);
        printf("&array+1 = %p\n",&array+1);
        /*后者比前者大10*4=40,&array表示一个指向 10个int 的数组指针*/
        printf("&array[0] = %p\n",&array[0]);
        printf("&array[0] +1 = %p\n",&array[0]+1);
        /*后者比前者大4*/
        return 0;
    }

    二维数组

    二维数组本质上也是一维数组,只是数组成员由基本数据类型变成了构造数据类型(一维数组)。

    定义形式:type name[m][n];其实等价于type[n] name[m],可以这么理解。一维数组的部分初始化和清零依然适用于二维数组。

    访问概念辨析:

    a表示第0行的首地址,a+i表示第i行的首地址。

    *(a+i)    等价于a[i]    等价于&a[i][0],表示第i行第0个元素的地址;

    *(a+i)+j    等价于a[i]+j    等价于&a[i][j],表示第i行的第j个元素的地址;

    *(*(a+i)+j)    等价于*(a[i]+j)    等价于a[i][j],表示第i行的第j个元素;

    二维数组在内存中开始连续的一维空间,所以依旧可以把二维数组当成一维数组来访问,但是需要强制转化:

    #include <stdio.h>
    int main()
    {
        int array[2][3] = {9,8,7,6,5,4};
        int i,j;
        for(i=0;i<2; i++)
        {
            for(j=0;j<3;j++)
            {
                printf("%d ",array[i][j]);
            }
            putchar(10);
        }
        int *p = (int *)array;
        for(i=0; i<6;i++)
        {
            printf("%d ",p[i]);
        }
        return 0;
    }

    相应的也可以把一维数组当二维数组来使用,但是这个也需要强制转换,如:int (*p)[2]=(int (*) [2])array;其中array是一维数组名。

    如何传递一个二维数组到函数中,例如有二维数组:int a[3][4];则接收它的函数参数是 function(int (*p)[4], n);

    二维数组中一些地址间的差异辨析:

    int main(void)
    {
        int a[3][5]={0};
        int *p=(int *)a;
        printf("%d\t,%d\n",sizeof(a),sizeof(p));//60 8
        printf("&a[0]=%p,&a[0]+1=%p\n",&a[0],&a[0]+1);//相差20=5*4
        printf("a=%p\t,a+1=%p\n",a,a+1);//相差20=5*4
        printf("&a=%p\t,&a+1=%p\n",&a,&a+1);//相差60=5*4*3
        return 0;
    }
    1. 二级指针比较典型的是用二级指针管理二维空间




基于STM32F407,使用DFS算法实现最短迷宫路径检索,分为三种模式:1.DEBUG模式,2. 训练模式,3. 主程序模式 ,DEBUG模式主要分析bug,测量必要数据,训练模式用于DFS算法训练最短路径,并将最短路径以链表形式存储Flash, 主程序模式从Flash中….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值