<pre id="bbfd9"><del id="bbfd9"><dfn id="bbfd9"></dfn></del></pre>

          <ruby id="bbfd9"></ruby><p id="bbfd9"><mark id="bbfd9"></mark></p>

          <p id="bbfd9"></p>

          <p id="bbfd9"><cite id="bbfd9"></cite></p>

            <th id="bbfd9"><form id="bbfd9"><dl id="bbfd9"></dl></form></th>

            <p id="bbfd9"><cite id="bbfd9"></cite></p><p id="bbfd9"></p>
            <p id="bbfd9"><cite id="bbfd9"><progress id="bbfd9"></progress></cite></p>

            嵌入式C語言內存操作技巧

            時間:2025-10-01 14:56:52 C語言

            嵌入式C語言內存操作技巧

              在嵌入式系統的編程中,常常要求在特定的內存單元讀寫內容,匯編有對應的MOV指令,而除C/C++以外的其它編程語言基本沒有直接訪問絕對地址的能力。嵌入式C語言高手煉成之內存操作是怎樣的?下面是相關的知識,歡迎閱讀。

              在嵌入式系統的實際調試中,多借助C語言指針所具有的對絕對地址單元內容的讀寫能力。以指針直接操作內存多發生在如下幾種情況:

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

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

              (3) 讀取在ROM或FLASH的特定單元所燒錄的漢字和英文字模。

              譬如:

              unsigned char *p = (unsigned char *)0xF000FF00;

              *p="11";

              以上程序的意義為在絕對地址0xF0000+0xFF00(80186使用16位段地址和16位偏移地址)寫入11。

              在使用絕對地址指針時,要注意指針自增自減操作的結果取決于指針指向的數據類別。上例中p++后的結果是p= 0xF000FF01,若p指向int,即:

              int *p = (int *)0xF000FF00;

              p++(或++p)的結果等同于:p = p+sizeof(int),而p-(或-p)的結果是p = p-sizeof(int)。

              記住:CPU以字節為單位編址,而C語言指針以指向的數據類型長度作自增和自減。理解這一點對于以指針直接操作內存是相當重要的。

              函數指針

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

              (1)C語言中函數名直接對應于函數生成的指令代碼在內存中的地址,因此函數名可以直接賦給指向函數的指針;

              (2)調用函數實際上等同于"調轉指令+參數傳遞處理+回歸位置入棧",本質上最核心的操作是將函數生成的目標代碼的首地址賦給CPU的PC寄存器;

              (3)因為函數調用的本質是跳轉到某一個地址單元的code去執行,所以可以"調用"一個根本就不存在的函數實體,暈?請往下看:

              請拿出你可以獲得的任何一本大學《微型計算機原理》教材,書中講到,186 CPU啟動后跳轉至絕對地址0xFFFF0(對應C語言指針是0xF000FFF0,0xF000為段地址,0xFFF0為段內偏移)執行,請看下面的代碼:

              typedef void (*lpFunction) ( ); /* 定義一個無參數、無返回類型的 */

              /* 函數指針類型 */

              lpFunction lpReset = (lpFunction)0xF000FFF0; /* 定義一個函數指針,指向*/

              /* CPU啟動后所執行第一條指令的位置 */

              lpReset(); /* 調用函數 */

              在以上的程序中,我們根本沒有看到任何一個函數實體,但是我們卻執行了這樣的函數調用:lpReset(),它實際上起到了"軟重啟"的作用,跳轉到CPU啟動后第一條要執行的指令的位置。

              記住:函數無它,唯指令集合耳;你可以調用一個沒有函數體的函數,本質上只是換一個地址開始執行指令!

              數組vs.動態申請

              在嵌入式系統中動態內存申請存在比一般系統編程時更嚴格的要求,這是因為嵌入式系統的內存空間往往是十分有限的,不經意的內存泄露會很快導致系統的崩潰。

              所以一定要保證你的malloc和free成對出現,如果你寫出這樣的一段程序:

              char * function(void)

              {

              char *p;

              p = (char *)malloc(…);

              if(p==NULL)

              …;

              … /* 一系列針對p的操作 */

              return p;

              }

              在某處調用function(),用完function中動態申請的內存后將其free,如下:

              char *q = function();

              …

              free(q);

              上述代碼明顯是不合理的,因為違反了malloc和free成對出現的原則,即"誰申請,就由誰釋放"原則。不滿足這個原則,會導致代碼的耦合度增大,因為用戶在調用function函數時需要知道其內部細節!

              正確的做法是在調用處申請內存,并傳入function函數,如下:

              char *p="malloc"(…);

              if(p==NULL)

              …;

              function(p);

              …

              free(p);

              p="NULL";

              而函數function則接收參數p,如下:

              void function(char *p)

              {

              … /* 一系列針對p的操作 */

              }

              基本上,動態申請內存方式可以用較大的數組替換。對于編程新手,筆者推薦你盡量采用數組!嵌入式系統可以以博大的胸襟接收瑕疵,而無法"海納"錯誤。畢竟,以最笨的方式苦練神功的郭靖勝過機智聰明卻范政治錯誤走反革命道路的楊康。

              給出原則:

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

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

              const在C++語言中則包含了更豐富的含義,而在C語言中僅意味著:"只能讀的普通變量",可以稱其為"不能改變的變量"(這個說法似乎很拗口,但卻最準確的表達了C語言中const的本質),在編譯階段需要的常數仍然只能以#define宏定義!故在C語言中如下程序是非法的:

              關鍵字const

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

              const int a;

              int const a;

              const int *a;

              int * const a;

              int const * a const;

              const int SIZE = 10;

              char a[SIZE]; /* 非法:編譯階段不能用到變量 */

              關鍵字volatile

              volatile變量可能用于如下幾種情況:

              (1) 并行設備的硬件寄存器(如:狀態寄存器,例中的代碼屬于此類);

              (2) 一個中斷服務子程序中會訪問到的非自動變量(也就是全局變量);

              (3) 多線程應用中被幾個任務共享的變量。


            【嵌入式C語言內存操作技巧】相關文章:

            嵌入式C語言優化技巧03-11

            C語言的內存使用03-06

            嵌入式C語言優化小技巧10-12

            C語言內存使用的常識10-14

            嵌入式c語言調試開關的技巧01-24

            C語言的底層操作09-05

            Go與C語言的操作02-15

            C語言位操作是11-26

            C語言內存地址基礎10-15

                    <pre id="bbfd9"><del id="bbfd9"><dfn id="bbfd9"></dfn></del></pre>

                    <ruby id="bbfd9"></ruby><p id="bbfd9"><mark id="bbfd9"></mark></p>

                    <p id="bbfd9"></p>

                    <p id="bbfd9"><cite id="bbfd9"></cite></p>

                      <th id="bbfd9"><form id="bbfd9"><dl id="bbfd9"></dl></form></th>

                      <p id="bbfd9"><cite id="bbfd9"></cite></p><p id="bbfd9"></p>
                      <p id="bbfd9"><cite id="bbfd9"><progress id="bbfd9"></progress></cite></p>
                      飘沙影院