首页 > 代码库 > 嵌入式:指针的指针、链表、UCOS 的 OSMemCreate 。

嵌入式:指针的指针、链表、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?

技术分享

 

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

技术分享

 

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)

技术分享

 

至此,结束。

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