初看,UCOS 的 OSMemCreate 代碼,感覺有點怪怪的,比如,把 指針指向的地址 強制轉換成 指針的指針的指向地址 ?那轉換後 指針的指針 又是什麼? ... (1)、p_link = (void **)p_addr; //把 p_addr 的值(即地址)賦給 p_link ,但是,類型不 ...
初看,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)
至此,結束。