嵌入式:指针的指针、链表、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
至此,结束。