嵌入式C語言記憶體操作程式設計重點知識點

才智咖 人氣:2.45W

本文主要講述了嵌入式系統C 程式設計中記憶體操作的相關技巧.掌握並深入理解關於資料指標、函式指標、動態申請記憶體、const 及volatile 關鍵字等的相關知識,是一個優秀的C 語言程式設計師的基本要求.當我們已經牢固掌握了上述技巧後,我們就已經學會了C 語言的99%,因為C 語言最精華的內涵皆在記憶體操作中體現.我們之所以在嵌入式系統中使用C 語言進行程式設計,99%是因為其強大的記憶體操作能力!

嵌入式C語言記憶體操作程式設計重點知識點

資料指標

在嵌入式系統的程式設計中,常常要求在特定的記憶體單元讀寫內容,彙編有對應的MOV指令,而除C/C++以外的其它程式語言基本沒有直接訪問絕對地址的能力.在嵌入式系統的實際除錯中,多借助C 語言指標所具有的對絕對地址單元內容的讀寫能力.以指標直接操作記憶體多發生在如下幾種情況:

(1) 某I/O 晶片被定位在CPU 的儲存空間而非I/O 空間,而且暫存器對應於某特定地址;

(2) 兩個CPU 之間以雙埠RAM 通訊,CPU 需要在雙埠RAM 的特定單元(稱為mail box)書寫內容以在對方CPU 產生中斷;

(3) 讀取在ROM 或FLASH 的特定單元所燒錄的漢字和英文字模.記住:CPU 以位元組為單位編址,而C 語言指標以指向的資料型別長度作自增和自減.理解這一點對於以指標直接操作記憶體是相當重要的.

函式指標

首先要理解以下三個問題:

(1)C 語言中函式名直接對應於函式生成的指令程式碼在記憶體中的地址,因此函式名可以直接賦給指向函式的指標;

(2)呼叫函式實際上等同於"調轉指令+引數傳遞處理+迴歸位置入棧",本質上最核心的操作是將函式生成的目的碼的首地址賦給CPU 的PC 暫存器;

(3)因為函式呼叫的本質是跳轉到某一個地址單元的code 去執行,所以可以"呼叫"一個根本就不存在的函式實體

陣列vs.動態申請

在嵌入式系統中動態記憶體申請存在比一般系統程式設計時更嚴格的要求,這是因為嵌入式系統的記憶體空間往往是十分有限的,不經意的記憶體洩露會很快導致系統的崩潰.所以一定要保證你的malloc 和free 成對出現給出原則:

(1)儘可能的選用陣列,陣列不能越界訪問(真理越過一步就是謬誤,陣列越過界限就光榮地成全了一個混亂的嵌入式系統);

(2)如果使用動態申請,則申請後一定要判斷是否申請成功了,並且malloc 和free應成對出現!

關鍵字const

const 意味著"只讀".區別如下程式碼的功能非常重要,也是老生長嘆,如果你還不知道它們的區別,而且已經在程式界摸爬滾打多年,那隻能說這是一個悲哀:

const int a;

int const a;

const int *a;

int * const a;

int const * a const;

(1)關鍵字const 的作用是為給讀你程式碼的人傳達非常有用的資訊.例如,在函式的形參前新增const 關鍵字意味著這個引數在函式體內不會被修改,屬於"輸入引數".在有多個形參的時候,函式的呼叫者可以憑藉引數前是否有const 關鍵字,清晰的辨別哪些是輸入引數,哪些是可能的`輸出引數.

(2)合理地使用關鍵字const 可以使編譯器很自然地保護那些不希望被改變的引數,防止其被無意的程式碼修改,這樣可以減少bug 的出現.

關鍵字volatile

C 語言編譯器會對使用者書寫的程式碼進行優化,譬如如下程式碼:

int a,b,c;

a = inWord(0x100); /*讀取I/O 空間0x100 埠的內容存入a 變數*/

b = a;

a = inWord (0x100); /*再次讀取I/O 空間0x100 埠的內容存入a 變數*/

c = a;

很可能被編譯器優化為:

int a,b,c;

a = inWord(0x100); /*讀取I/O 空間0x100 埠的內容存入a 變數*/

b = a;

c = a;

但是這樣的優化結果可能導致錯誤,如果I/O 空間0x100 埠的內容在執行第一次讀操作後被其它程式寫入新值,則其實第2 次讀操作讀出的內容與第一次不同,b 和c的值應該不同.在變數a 的定義前加上volatile 關鍵字可以防止編譯器的類似優化,正確的做法是:

volatile int a;

volatile 變數可能用於如下幾種情況:

(1) 並行裝置的硬體暫存器(如:狀態暫存器,例中的程式碼屬於此類);

(2) 一箇中斷服務子程式中會訪問到的非自動變數(也就是全域性變數);

(3) 多執行緒應用中被幾個任務共享的變數.