嵌入式程序設(shè)計(jì)之玩轉(zhuǎn)內(nèi)存
掃描二維碼
隨時(shí)隨地手機(jī)看文章
數(shù)據(jù)指針
在嵌入式系統(tǒng)編程中,經(jīng)常會對特定的內(nèi)存單元進(jìn)行讀寫操作。在匯編中有對應(yīng)的MOV指令,而在C/C++以及其他高級語言中基本沒有直接操作絕對地址的能力。而在嵌入式系統(tǒng)的實(shí)際開發(fā)調(diào)試過程中,大多情況會借助C語言指針多具備的對絕對地址單元內(nèi)容的讀寫能力。
直接使用指針操作內(nèi)存,主要分為以下幾種情況:
-
某I/O芯片被定位在CPU的存儲空間而非I/O空間,而且寄存器對應(yīng)的是特定的地址
-
兩個(gè)CPU之間以雙端口RAM進(jìn)行通信,CPU需要在雙端口RAM的特定單元(mail box)書寫內(nèi)容以在對方CPU產(chǎn)生中斷。
-
讀寫ROM或FLASH的特定單元所燒錄的漢字或英文字模
////< 在絕對地址0x01寫入10 unsigned char *p = (unsigned char *)0x01; *p = 10;
使用絕對地址時(shí),需要注意指針自增自減的結(jié)果取決于指針指向的數(shù)據(jù)類型。
int *p = (int *)0x01;
p++的結(jié)果為:p = p + sizeof(int)
p--的結(jié)果為:p = p - sizeof(int)
cpu以字節(jié)為單位編址,而C語言指針以指向的數(shù)據(jù)類型長度作為自增自減
函數(shù)指針
-
C 語言中函數(shù)名直接對應(yīng)于函數(shù)生成的指令代碼在內(nèi)存中的地址,因此函數(shù)名可以直接賦給指向函數(shù)的指針
-
調(diào)用函數(shù)實(shí)際上等同于"調(diào)轉(zhuǎn)指令+參數(shù)傳遞處理+回歸位置入棧",本質(zhì)上最核心的操作是將函數(shù)生成的目標(biāo)代碼的首地址賦給CPU 的PC 寄存器
-
因?yàn)楹瘮?shù)調(diào)用的本質(zhì)是跳轉(zhuǎn)到某一個(gè)地址單元的code 去執(zhí)行,所以可以"調(diào)用"一個(gè)根本就不存在的函數(shù)實(shí)體
typedef void (*lpFunction) ( ); ////< 定義一個(gè)無參數(shù)、無返回類型的函數(shù)指針類型 ////< 定義一個(gè)函數(shù)指針,指向CPU 啟動后所執(zhí)行第一條指令的位置 lpFunction lpReset = (lpFunction)0xF000FFF0; lpReset(); ////< 函數(shù)調(diào)用
《微型計(jì)算機(jī)原理》中講到,186 CPU 啟動后跳轉(zhuǎn)至絕對地址0xFFFF0,該地址對應(yīng)到C語言中為上述例子中的0xF000FFF0,其中0xF000為段地址,0xFFF0為段內(nèi)偏移。
在上述例子中,根本沒有定義函數(shù),但是卻能夠執(zhí)行l(wèi)pReset()函數(shù)的調(diào)用,它實(shí)際的作用為"軟重啟",使程序跳轉(zhuǎn)到CPU啟動后第一條要執(zhí)行的執(zhí)行位置。
動態(tài)申請內(nèi)存
在嵌入式系統(tǒng)中動態(tài)內(nèi)存申請存在比一般系統(tǒng)編程時(shí)更嚴(yán)格的要求,這是因?yàn)榍度胧较到y(tǒng)的內(nèi)存空間往往是十分有限的,不經(jīng)意的內(nèi)存泄露會很快導(dǎo)致系統(tǒng)的崩潰。
因此,maloc和free一般要保證成對出現(xiàn)。
char *Function(void) { char *p = NULL; p = (char *)malloc(sizeof(char)); ... return p; } void main() { char *q = Function(); ... free(q); }
上面這個(gè)例子明顯是不合理的,因?yàn)樗`反了"誰申請,就由誰釋放"的原則。若程序不滿足這個(gè)原則的話,會導(dǎo)致代碼的耦合度增大,使用者需要在調(diào)用的時(shí)候知道Function()函數(shù)中的具體實(shí)現(xiàn)。
正確做法應(yīng)該如下:
void Function(char*p) { ... } void main() { char *q = malloc(sizeof(char)); ... Function(q); ... free(q); }