對uC OS II內二維指標的研究

2021-05-24 02:06:38 字數 3806 閱讀 8433

東莞權智集團 范偉

mail:

[email protected]

;[email protected]

本文若有錯誤之處,歡迎來信指正。

uc/os-ii

記憶體管理函式內最難理解的部分就是二維指標,本文以**並茂的方式對二維指標進行了詳細分析與講解。看完本文,相信

對c裡面指標的概念又會有進一步的認識。

一、osmemcreate( ) 函式中有如下語句:

os_mem *pmem;

int8u *pblk; 

void **plink;

int32u i;

plink = (void **)addr;

//指向所申請記憶體分割槽的起始位址

pblk = (int8u *)addr + blksize;

//所申請記憶體的第二個block的起始位址

for (i = 0; i < (nblks - 1); i++)

//依次申請nblks個block,鏈結成單向鍊錶

紅色部分是初學者對本函式最難理解的部分,因為其用到了

二維指標。二維指標就是指向指標的指標,他的內容是乙個目標變數的位址,也就是說仍然是乙個指標,對二維指標取兩次內容才能取到目標變數的內容。這裡先複習一下指標的知識:

int a = 5;

int *ptr;

ptr=&a;//ptr

指標是位址,指向變數a所在位址。

則可以得出:

*ptr=a;//

即指標ptr指向變數a所在位址,*ptr的值就是a的值5

由此類推,對於二維指標變數**plink,指標plink是位址,*plink是plink所指向的位址內的資料,不過同時這個資料也是乙個指標,並且**plink是指標(*plink)所指向的位址內的資料。

一維指標所指向的位址內存放的是普通資料,如上述ptr指標所指向的位址內存放的是int型資料5。

二維指標所指向的位址內存放的是乙個一維指標,如上述指標plink所指向的位址內存放的是指標*plink。

下面詳細分析上述osmemcreate函式內的語句: 1

、plink = (void **)addr;

addr

本來是乙個一維指標,指向所申請記憶體分割槽的起始位址。本句將addr強制轉換為二維指標(注意經過強制轉換後addr指標本身指向的位址是沒有變化的),並將addr位址值賦給plink。則plink的記憶體中儲存的是addr的值,即plink也指向addr所指向的分割槽起始位址,並且這個位址內存放的內容是指標(*plink)

,但指標(*plink)還未指向具體的位址。在這條語句之前,這個起始位址內的資料內容是未知的(由編譯器分配的)。記憶體分割槽結構見下圖1所示(假設申請的記憶體區有4個block)。

在這個函式當中,我們想把addr指向的二維陣列,分割成大小相同的若干塊,並用指標把它們鏈結起來,鏈結指標放在每個block的首位址。但由於addr是一維指標,它指向的內容不會被解釋成乙個位址,而是一般的內容。我們要在這些block的首位址內存放指標,所以將addr強制轉換成二維指標的目的就是讓編譯器將addr指向的內容解釋成位址,也就是乙個指標。

再將addr賦值給plink(讓plink去執行連線的操作),使plink與addr指向同乙個位址。*plink就是取plink與addr指向位址單元的內容,而這個內容是乙個指標,也就是在以前addr指向的地方放上指標*plink。 2

、pblk = (int8u *)addr + blksize;

讓pblk指向所申請記憶體的第二個block的起始位址,見下圖2所示。

因為addr是void型的,要強制轉換為int8u型。

3、*plink = (void *)pblk;

//實際上是*plink = pblk,因為pblk是int8u型的,要強制轉換為void型

在for迴圈內對二維指標plink執行取內容操作(其內容為指標),*plink也是乙個指標了(plink指標所代表的位址的內容),將下乙個block的首位址賦值給*plink,使它指向的地方改為下乙個blcok開始的位址處。

起始位址內的指標*plink被賦值為pblk,所以*plink與pblk一樣指向下乙個blcok開始的位址處。

如圖3所示。

第乙個block首位址內的內容為乙個指標,該指標指向下乙個block首位址。這個位址內存放的就是*plink的內容**plink。

只不過我們並不需要用到這個**plink。

4、plink  = (void **)pblk;

功能與plink = (void **)addr 相似,

即plink也指向第二個block的起始位址

,並且使這個位址內存放的是指標(*plink)。

注意:因為plink所指向的位址變了,此時pblk所指向的位址

內的內容由原來的**plink變為了*plink指標。

並且 *plink還未被賦值,則**plink值是未知的 5

、pblk   = pblk + blksize;

pblk

不斷的下移,以指向再下乙個block的開始處。

pblk(new)= pblk(old)+blksize

當再次進行for迴圈時,重複上述過程,利用每個block首位址內的指標將每個block鏈結起來組成空閒塊鍊錶。

同樣,*plink被賦值後,指向pblk所指向的位址,則該位址的

內容為**plink,只不過我們並不需要取出**plink。

6、pmem->osmemfreelist = addr;

/*pmem->osmemfreelist

指向空閒塊鍊錶第乙個block首位址

在完成for迴圈後,使pmem->osmemfreelist指向addr,組成完整的空閒塊鍊錶。

總結:進行(void**)強制轉換的目的其實就是為了把所指向的位址的內容轉換成乙個指標。

二、在osmemget( )函式內同樣有一條強制轉換為二維指標的指令:

void      *pblk;

執行操作:pmem->osmemfreelist =*

(void **)pblk;

pblk

被強制轉換為二維指標,然後取出其內容*pblk,也就是pblk位址內存放的鏈結指標。

意味著取出pblk的內容,由於pblk被強制轉換成了二維指標,所以它的內容就不是一般的值,而是乙個指標(這個指標指向下乙個block首位址)。

三、在int8uosmemput (os_mem*pmem, void *pblk) 函式內同樣有類似的指令:

①*(void **)pblk= pmem->osmemfreelist;

// 將欲釋放的塊新增到空閒塊鍊錶最前面

② pmem->osmemfreelist = pblk;

首先要明白pmem->osmemfreelist是指向空閒塊鍊錶第乙個block的首位址的。

語句①將pblk強制轉換為二維指標後,再將pmem->osmemfreelist賦值給pblk的內容(*pblk指標)。根據osmemput函式的定義,pblk是函式的形參,是欲釋放的塊的首位址。所以也就是將pmem->osmemfreelist指標放入欲釋放的塊的首位址內,此處強制轉換為二維指標的目的就是讓欲釋放的塊的首位址內能存放指標。則這個塊的首位址內的指標就是指向原先空閒塊鍊錶第乙個block的首位址的,也就是說這個塊變成了空閒塊鍊錶第乙個block,實現了將釋放的塊新增到空閒塊鍊錶最前面的目的。

然後語句②更新pmem->osmemfreelist指標,使其指向新釋放的塊的首位址,這樣就保證了pmem->osmemfreelist始終指向空閒塊鍊錶第乙個block首位址。

參考文章: http://blog.csdn.net/uestczhangchao/archive/2010/05/14/5589476.aspx

對uC OS II內二維指標的研究

東莞權智集團 范偉 mail fanwei326 163.com wfan gsl.com.cn uc os ii記憶體管理函式內最難理解的部分就是二維指標,本文以 並茂的方式對二維指標進行了詳細分析與講解。看完本文,相信對c裡面指標的概念又會有進一步的認識。一 osmemcreate 函式中有如下...

uC OS II記憶體管理函式的二維指標

uc os ii記憶體管理函式內最難理解的部分就是二維指標,本文以 並茂的方式對二維指標進行了詳細分析與講解。看完本文,相信對c裡面指標的概念又會有進一步的認識。一 osmemcreate 函式中有如下語句 os mem pmem int8u pblk void plink int32u i pli...

二維陣列與二維指標

1.二維陣列的儲存是線性的,可以通過一維指標的方式訪問。如一下 int map 5 5 int mapd map 0 0 則 map i j mapd i 5 j 而利用二維陣列線性儲存的特性,可以將二維陣列當作一維指標方便的在函式之間傳遞 如 將乙個二維陣列賦值給乙個動態二維陣列,引數設定為一維指...