• 嵌入式:指针的指针、链表、UCOS 的 OSMemCreate 。


    初看,UCOS 的 OSMemCreate 代码,感觉有点怪怪的,比如,把 指针指向的地址 强制转换成 指针的指针的指向地址 ?那转换后 指针的指针 又是什么?

    void  OSMemCreate (OS_MEM       *p_mem,
                       CPU_CHAR     *p_name,
                       void         *p_addr,
                       OS_MEM_QTY    n_blks,
                       OS_MEM_SIZE   blk_size,
                       OS_ERR       *p_err)
    {
    #if OS_CFG_ARG_CHK_EN > 0u
        CPU_DATA       align_msk;
    #endif
        OS_MEM_QTY     i;
        OS_MEM_QTY     loops;
        CPU_INT08U    *p_blk;
        void         **p_link;
    

    ...

        p_link = (void **)p_addr;                               /* Create linked list of free memory blocks               */
        p_blk  = (CPU_INT08U *)p_addr;
        loops  = n_blks - 1u;
        for (i = 0u; i < loops; i++) {
            p_blk +=  blk_size;
           *p_link = (void  *)p_blk;                            /* Save pointer to NEXT block in CURRENT block            */
            p_link = (void **)(void *)p_blk;                    /* Position     to NEXT block                             */
        }
       *p_link             = (void *)0;                         /* Last memory block points to NULL                       */
    

    (1)、p_link = (void **)p_addr;       //把 p_addr 的值(即地址)赋给 p_link ,但是,类型不一样,所以 强制转换 。

    (2)、p_blk  = (CPU_INT08U *)p_addr;  //强制转换,因为 p_addr 为 void* 形参 ,任意类型的指针。

    (3)、loops  = n_blks - 1u;         //循环次数

    (4)、for (i = 0u; i < loops; i++) {     //循环

    (5)、 p_blk +=  blk_size;          //把地址增加 一个块空间 大小

    (6)、*p_link = (void  *)p_blk;      //把自增后的地址,赋值给 *p_link ,即写入到 *(p_addr + blk_size )数组里,因为,在(1)把p_addr 地址给了p_link。

    (7)、p_link = (void **)(void *)p_blk;   //p_blk,是CPU_INT08U * 类型指针,所以,先强制转换成(void *)任意类型的,然后,再用(void **)强制转换,同1;

    (8)、}                  //循环结束
    (9)、*p_link = (void *)0;         //在链表结尾赋NULL。

    在这里,**p_link 无意义,因为 *p_link  相当于*(p_addr + loops * blk_size ),即 数组的值, 那**p_link (*值)是什么?如果这个值,刚好是32位且申请过的空间,如 0x12345678,那么**p_link,也许就有意义了?

    还有,既然**p_link ,都没用到过,那是否用 一级指针 就行了?没必要用 二级指针?

    于是用 Xcode 做了些测试,如下:

    1、传统教科书式用法,c -> b ->a

    2、模仿UCOS的方法,b[0]=(a的地址),b[1]=(a的地址+3)。

    2-1、发现有问题,调了下发现,任意类型的指针void *,自增,只增加1?

        后续:后来用MDK试了下,void *,不能++。编译器的原因吧。

    2-2、试了下地址,增加一个指针大小,就可以了。在这里,sizeof(void *)  = sizeof(long int *) = 8 。用MAC的Xcode测试的。

        后续:这里应该 +sizeiof(long int) 比较好。

    3、同样模仿UCOS的写法,区别于2,指针类型都用 long int * ,不用 void * 。

    3-1、和2相反,用指针自增是对的。

    3-2、和2相反,加一个指针大小是错的。

    4、后来,想,既然UCOS,用了指针的指针,但都没用到**p_link,只用到一级指针,那我是否可以把p_link都参数都加上*,变成使用**p_link,和*p_link?

    结果一开始就错了。编译没问题,语法没错误,但是,p_p_b没有指向任何地址,不能对*p_p_b赋值。

    5、对4的修改,与UCOS写法一样用了指针的指针,**p_p_b 相当于**p_link。用**p_p_b来修改外面的数组,用p_p_b来指向不断自增的外面数组的地址,且不需要重复 p_p_b = &p_b(UCOS写法需要,见(7),因为,UCOS,相当于用一级指针,地址改变,需要重复赋地址,而,这里二级指针指向了一个一级指针,一级变,二级会跟踪)。

    6、再细想,既然UCOS只用到一级指针的效果。那么我是否可以直接用1级指针。

          后续:这里有误,本来的效果应该是p_b_1++,类似UCOS的写法,需要 for 不断的p_b_2 = p_b_1

    至此,结束。

  • 相关阅读:
    项目三.
    项目二
    项目一.
    第三季-第27课-Shell脚本高级编程
    第三季-第26课-守护进程设计
    第三季-第26课-网络并发服务器设计
    第三季-第25课-UDP通讯程序设计
    刷新页面
    css让超出文字省略号
    css3 背景透明
  • 原文地址:https://www.cnblogs.com/leonlincq/p/6291474.html
Copyright © 2020-2023  润新知