乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      如何優(yōu)化代碼

       guitarhua 2013-04-21

      如何優(yōu)化代碼

      編程 2010-05-25 23:10:09 閱讀99 評(píng)論1   字號(hào): 訂閱

      縮小編譯代碼 size 的幾種方式:

      (A)    邏輯與算法:

      合理的工作邏輯與算法. 一般而言, Code 永遠(yuǎn)是工程師的邏輯思維的體現(xiàn). 無(wú)論是實(shí)現(xiàn) function target or 構(gòu)建 system struction, 邏輯思維的能力高低, 對(duì) code size 具有深度影響(甚至對(duì)整個(gè) project 的成功實(shí)現(xiàn), 具有決定性的影響).

       

      (B) 編譯器的配置:

      1. 將編譯器的 size 優(yōu)化調(diào)整到 high級(jí)別.

      2.   如果我們是 arm 的 user, 應(yīng)選擇 Thumb mode, 而不是 Arm mode.

      我們無(wú)意在這里討論16-bit thumb指令集 與 32-bit arm 指令集有何具體異同. 我們僅僅從 mcu 的datasheet 中尋找到如下解釋(討論了兩者最終表現(xiàn)力): “工作在與 arm mode 相同的 32-bit 寄存器上, thumb code 保持了絕大部分的 arm 的表現(xiàn)力(的同時(shí)), Thumb code能夠提供高達(dá) 65% 的(作為比較的)arm code size.”

       

      (C) 謹(jǐn)慎使用任何標(biāo)準(zhǔn)/編譯器提供的 C Library function:

      謹(jǐn)慎使用編譯器提供的任何C Library function, 如果必需, 盡量自行完成需要的函數(shù)功能.

      1. 謹(jǐn)慎使用string相關(guān)函數(shù)

      無(wú)論是 sprintf(), atoi(), ntop(),都會(huì)帶來(lái)size 的顯著增加. 如有可能, 我們應(yīng)當(dāng)自行完成我們需要的類(lèi)似的 functions.

       

      2. 謹(jǐn)慎使用 time 相關(guān)函數(shù): 舉例說(shuō) localtime(), etc 等函數(shù).

       

      3.   謹(jǐn)慎使用 math 函數(shù), 盡量不要包含 math.h
      作為兩個(gè)比較的的例子是, 在同等編譯條件下, fasbs()可能多耗費(fèi) about 200bytes. sqrt() 可能會(huì)多耗費(fèi) about 3.5k bytes.

       

      (D) 數(shù)據(jù)類(lèi)型與編程習(xí)慣

      1.       盡量避免 char(U8/S8), short(U16/S16) 的定義, 而使用 int(U32/S32) 的定義.

      對(duì)于從 8-bit來(lái)到 arm world 的 engineer, 可能份外不習(xí)慣這個(gè)轉(zhuǎn)變吧?

      C/C++ compiler reference document 明確指出: 只要可能, 就應(yīng)使用 int or long 來(lái)替代 char or short, 從而避免了符號(hào)位擴(kuò)展與zero拓展. 而且, 對(duì) loop index 使用 int/long 將減小 code 產(chǎn)生. 特別要指出, 在 thumb mode, stack pointer(SP) 被嚴(yán)格定義為 32-bit data types(因此更應(yīng)該使用 int/long).

             一個(gè)令人有興趣的簡(jiǎn)單實(shí)驗(yàn)?zāi)軌蜃C明, 所謂的”sign extension or zero extensize”帶來(lái)的額外代碼消耗. 在一份c的源文件中, 如果我們定義了 U8 global_data. 簡(jiǎn)單將其改為 U32 global_data. Then do rebuild all, we will find the code size decrease 4 bytes… ; ) 但是要提及的是, 我們的項(xiàng)目經(jīng)驗(yàn)說(shuō)明這個(gè)way往往還會(huì)帶來(lái)一個(gè)其他的效果: DATA size在這種情形下或略有增加.

       

      2.       盡量避免使用帶符號(hào)位的數(shù)據(jù)類(lèi)型.

       

      3.       盡量避免 long(8-byte) 的定義.

       

      4.       Bitfields 與 packed structures 將產(chǎn)生大而且慢的代碼.

      對(duì)于 packed structures, 作者在相同的 blog 主頁(yè)發(fā)表了專(zhuān)題文章, 指出了選擇使用 packed structures, 仍然可以享受到盡可能小的 code size, 以及保持access speed的處理方式. 檢索作者的 blog, 或檢查全部文章列表, 將會(huì)發(fā)現(xiàn)該篇文章. 在我們的項(xiàng)目經(jīng)驗(yàn)中, 在 32k bytes 左右的 project 中, 我們獲得了額外的大約 2k bytes 的節(jié)省的 code size.

       

      5.       盡量不要定義 float, double.

      在一些運(yùn)算中, 我們常常將牽涉到如下步驟: 將float *10e(小數(shù)點(diǎn)后位數(shù)), 將float轉(zhuǎn)化為U32進(jìn)行運(yùn)算. 結(jié)果在/10e(相應(yīng)位數(shù)). 運(yùn)算精度在這里被降低了. 但這完全取決于我們的工作目標(biāo): 在不復(fù)雜的算法中, 避免了浮點(diǎn)運(yùn)算的使用(以上討論, 均假設(shè)我們的 mcu 不包含浮點(diǎn)運(yùn)算協(xié)處理器). Reference 也一再?gòu)?qiáng)調(diào)沒(méi)有math協(xié)處理器, 浮點(diǎn)數(shù)據(jù)類(lèi)型效率低下.

       

      6.       reference 指出, 盡量定義 local 變量. 減少 static 或 global 變量的定義, 這樣將幫助優(yōu)化的過(guò)程. 且local 變量盡量少使用 &. Reference 指出, 這種定義將放置變量到 memory 中, 而不能放置到處理器的 register 中(代碼會(huì)變大變慢). 另外也不能有助于優(yōu)化器進(jìn)行優(yōu)化.

       

      7.       *(2的倍數(shù)), 或 /(2的倍數(shù)), 使用 “<<” 以及 “>>” 操作.

       

      8.   應(yīng)保持?jǐn)?shù)據(jù)變量的type 定義的一致性, 在運(yùn)算中, 盡量減少類(lèi)似 U32 -> U16 -> U32 的不必要的強(qiáng)制轉(zhuǎn)化過(guò)程.

       

      9.   定義字符串為全局變量, 在 ram 富余的情況下, 這是一個(gè)利用 ram 來(lái)分擔(dān)降低 code size 的技巧.

      構(gòu)建代碼的過(guò)程, 不僅僅是理性思維落實(shí)為真實(shí)世界邏輯的過(guò)程, 我們覺(jué)得, 也是和編譯器進(jìn)行交互的過(guò)程. 我們所作所為, 需要實(shí)現(xiàn)目的之邏輯, 我覺(jué)得也需要, "討好"編譯器, 讓它為我們的代碼, 生產(chǎn) size 和 speed 都得到優(yōu)化的job.

       

      如何優(yōu)化C語(yǔ)言代碼

      來(lái)源:互聯(lián)網(wǎng) 時(shí)間:2008-02-23
      西部數(shù)碼-全國(guó)虛擬主機(jī)10強(qiáng)!40余項(xiàng)虛擬主機(jī)管理功能,全國(guó)領(lǐng)先!雙線多線虛擬主機(jī)南北訪問(wèn)暢通無(wú)阻!免費(fèi)贈(zèng)送企業(yè)郵局,.CN域名,自助建站480元起,免費(fèi)試用7天,滿(mǎn)意再付款! VPS主機(jī)租用266元/月(1G內(nèi)存)!
       1、選擇合適的算法和數(shù)據(jù)結(jié)構(gòu) 
        應(yīng)該熟悉算法語(yǔ)言,知道各種算法的優(yōu)缺點(diǎn),具體資料請(qǐng)參見(jiàn)相應(yīng)的參考資料,有很多電腦書(shū)籍上都有介紹。將比較慢的順序查找法用較快的二分查找或亂序查找法代替,插入排序或冒泡排序法用快速排序、合并排序或根排序代替,都能夠大大提高程式執(zhí)行的效率。.選擇一種合適的數(shù)據(jù)結(jié)構(gòu)也很重要,比如您在一堆隨機(jī)存放的數(shù)中使用了大量的插入和刪除指令,那使用鏈表要快得多。數(shù)組和指針語(yǔ)句具備十分密碼的關(guān)系,一般來(lái)說(shuō),指針比較靈活簡(jiǎn)潔,而數(shù)組則比較直觀,容易理解。對(duì)于大部分的編譯器,使用指針比使用數(shù)組生成的代碼更短,執(zhí)行效率更高。但是在Keil中則相反,使用數(shù)組比使用的指針生成的代碼更短。。 

        2。。。

        3、使用盡量小的數(shù)據(jù)類(lèi)型
       
      能夠使用字符型(char)定義的變量,就不要使用整型(int)變量來(lái)定義;能夠使用整型變量定義的變量就不要用長(zhǎng)整型(long int),能不使用浮點(diǎn)型(float)變量就不要使用浮點(diǎn)型變量。當(dāng)然,在定義變量后不要超過(guò)變量的作用范圍,假如超過(guò)變量的范圍賦值,C編譯器并不報(bào)錯(cuò),但程式運(yùn)行結(jié)果卻錯(cuò)了,而且這樣的錯(cuò)誤很難發(fā)現(xiàn)。 
      在ICCAVR中,能夠在Options中設(shè)定使用printf參數(shù),盡量使用基本型參數(shù)(%c、 版權(quán)申明:本站文章均來(lái)自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系028-86262244-215,我們收到后立即刪除,謝謝! 
      %d、%x、%X、%u和%s格式說(shuō)明符),少用長(zhǎng)整型參數(shù)(%ld、%lu、%lx和%lX格式說(shuō)明 符),至于浮點(diǎn)型的參數(shù)(%f)則盡量不要使用,其他C編譯器也相同。在其他條件不 變的情況下,使用%f參數(shù),會(huì)使生成的代碼的數(shù)量增加很多,執(zhí)行速度降低。 

        4、使用自加、自減指令 
        通常使用自加、自減指令和復(fù)合賦值表達(dá)式(如a-=1及a =1等)都能夠生成高質(zhì)量的
      程式代碼,編譯器通常都能夠生成inc和dec之類(lèi)的指令,而使用a=a 1或a=a-1之類(lèi)
      的指令,有很多C編譯器都會(huì)生成二到三個(gè)字節(jié)的指令。在AVR單片適用的ICCAVR、 GCCAVR、IAR等C編譯器以上幾種書(shū)寫(xiě)方式生成的代碼是相同的,也能夠生成高質(zhì)量 的inc和dec之類(lèi)的的代碼。 

        5、減少運(yùn)算的強(qiáng)度 
        能夠使用運(yùn)算量小但功能相同的表達(dá)式替換原來(lái)復(fù)雜的的表達(dá)式。如下: 

      (1)、求余運(yùn)算。 
      a=a%8; 
      能夠改為: 
      a=a&7; 
      說(shuō)明:位操作只需一個(gè)指令周期即可完成,而大部分的C編譯器的“%”運(yùn)算均是調(diào) 用子程式來(lái)完成,代碼長(zhǎng)、執(zhí)行速度慢。通常,只需要是求2n方的余數(shù),均可使用 位操作的方法來(lái)代替。 

      (2)、平方運(yùn)算 
      a=pow(a,2.0); 
      能夠改為: 
      a=a*a; 
      說(shuō)明:在有內(nèi)置硬件乘法器的單片機(jī)中(如51系列),乘法運(yùn)算比求平方運(yùn)算快得多,因?yàn)楦↑c(diǎn)數(shù)的求平方是通過(guò)調(diào)用子程式來(lái)實(shí)現(xiàn)的,在自帶硬件乘法器的AVR單片機(jī)中,如ATMega163中,乘法運(yùn)算只需2個(gè)時(shí)鐘周期就能夠完成。既使是在沒(méi)有內(nèi)置 硬件乘法器的AVR單片機(jī)中,乘法運(yùn)算的子程式比平方運(yùn)算的子程式代碼短,執(zhí)行速度快。 特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn),本站所提供的攝影照片,插畫(huà),設(shè)計(jì)作品,如需使用,請(qǐng)與原作者聯(lián)系. 
      假如是求3次方,如: 
      a=pow(a,3.0); 
      更改為: 
      a=a*a*a; 
      則效率的改善更明顯。 

      (3)、用移位實(shí)現(xiàn)乘除法運(yùn)算 
      a=a*4; 
      b=b/4; 
      能夠改為: 
      a=a<<2; 
      b=b>>2; 
      說(shuō)明:通常假如需要乘以或除以2n,都能夠用移位的方法代替。在ICCAVR中,假如 乘以2n,都能夠生成左移的代碼,而乘以其他的整數(shù)或除以任何數(shù),均調(diào)用乘除法 子程式。用移位的方法得到代碼比調(diào)用乘除法子程式生成的代碼效率高。實(shí)際上, 只要是乘以或除以一個(gè)整數(shù),均能夠用移位的方法得到結(jié)果,如: 
      a=a*9 
      能夠改為: 
      a=(a<<3) a 

        6、循環(huán) 

      (1)、循環(huán)語(yǔ) 
      對(duì)于一些無(wú)需循環(huán)變量參加運(yùn)算的任務(wù)能夠把他們放到循環(huán)外面,這里的任務(wù)包括表達(dá)式、函數(shù)的調(diào)用、指針運(yùn)算、數(shù)組訪問(wèn)等,應(yīng)該將沒(méi)有必要執(zhí)行多次的操作全部集合在一起,放到一個(gè)init的初始化程式中進(jìn)行。 

      (2)、延時(shí)函數(shù): 
      通常使用的延時(shí)函數(shù)均采用自加的形式: 
      void delay (void) 

      unsigned int i; 
      for (i=0;i<1000;i ) 


      將其改為自減延時(shí)函數(shù): 
      void delay (void) 

      unsigned int i; 
      for (i=1000;i>0;i--) .. 


        兩個(gè)函數(shù)的延時(shí)效果相似,但幾乎任何的C編譯對(duì)后一種函數(shù)生成的代碼均比前一種代碼少1~3個(gè)字節(jié),因?yàn)閹缀跞魏蔚腗CU均有為0轉(zhuǎn)移的指令,采用后一種方式能夠生成這類(lèi)指令。在使用while循環(huán)時(shí)也相同,使用自減指令控制循環(huán)會(huì)比使用自加指令控制循環(huán)生成的代碼更少1~3個(gè)字母。但是在循環(huán)中有通過(guò)循環(huán)變量“i”讀寫(xiě)數(shù)組的指令時(shí),使用預(yù)減循環(huán)時(shí)有可能使數(shù)組超界,要引起注意。 

      (3)while循環(huán)和do…while循環(huán) 
      用while循環(huán)時(shí)有以下兩種循環(huán)形式: 
      unsigned int i; 
      i=0; 
      while (i<1000) 

      i ; 
      //用戶(hù)程式 

      或: 
      unsigned int i; 
      i=1000; 
      do 
      i--; 
      //用戶(hù)程式 
      while (i>0); 
      在這兩種循環(huán)中,使用do…while循環(huán)編譯后生成的代碼的長(zhǎng)度短于while循環(huán)。 

        7、查表 
        在程式中一般不進(jìn)行很復(fù)雜的運(yùn)算,如浮點(diǎn)數(shù)的乘除及開(kāi)方等,連同一些復(fù)雜的數(shù)學(xué)模型的插補(bǔ)運(yùn)算,對(duì)這些即消耗時(shí)間又消費(fèi)資源的運(yùn)算,應(yīng)盡量使用查表的方式,并且將數(shù)據(jù)表置于程式存儲(chǔ)區(qū)。假如直接生成所需的表比較困難,也盡量在啟了,減少了程式執(zhí)行過(guò)程中重復(fù)計(jì)算的工作量。 

        8、其他 
        比如使用在線匯編及將字符串和一些常量保存在程式存儲(chǔ)器中,均有利于優(yōu)化
       
      如何優(yōu)化C語(yǔ)言代碼(程序員必讀)------(1)

      如何優(yōu)化C語(yǔ)言代碼(程序員必讀)[轉(zhuǎn)]http://www./ 2008-11-17  網(wǎng)絡(luò) 點(diǎn)擊:69  [ 評(píng)論 ]
      文章搜索:     【點(diǎn)擊打包該文章】 被過(guò)濾廣告 
      【本站開(kāi)通在線QQ討論群】

      1、選擇合適的算法和數(shù)據(jù)結(jié)構(gòu)
            應(yīng)該熟悉算法語(yǔ)言,知道各種算法的優(yōu)缺點(diǎn),具體資料請(qǐng)參見(jiàn)相應(yīng)的參考資料,有很多計(jì)算機(jī)書(shū)籍上都有介紹。將比較慢的順序查找法用較快的二分查找或亂序查找法代替,插入排序或冒泡排序法用快速排序、合并排序或根排序代替,都可以大大提高程序執(zhí)行的效率。.選擇一種合適的數(shù)據(jù)結(jié)構(gòu)也很重要,比如你在一堆隨機(jī)存放的數(shù)中使用了大量的插入和刪除指令,那使用鏈表要快得多。數(shù)組與指針語(yǔ)句具有十分緊密的關(guān)系,一般來(lái)說(shuō),指針比較靈活簡(jiǎn)潔,而數(shù)組則比較直觀,容易理解。對(duì)于大部分的編譯器,使用指針比使用數(shù)組生成的代碼更短,執(zhí)行效率更高。但是在Keil中則相反,使用數(shù)組比使用的指針生成的代碼更短。。


      3、使用盡量小的數(shù)據(jù)類(lèi)型
            能夠使用字符型(char)定義的變量,就不要使用整型(int)變量來(lái)定義;能夠使用整型變量定義的變量就不要用長(zhǎng)整型(long int),能不使用浮點(diǎn)型(float)變量就不要使用浮點(diǎn)型變量。當(dāng)然,在定義變量后不要超過(guò)變量的作用范圍,如果超過(guò)變量的范圍賦值,C編譯器并不報(bào)錯(cuò),但程序運(yùn)行結(jié)果卻錯(cuò)了,而且這樣的錯(cuò)誤很難發(fā)現(xiàn)。
            在ICCAVR中,可以在Options中設(shè)定使用printf參數(shù),盡量使用基本型參數(shù)(%c、%d、%x、%X、%u和%s格式說(shuō)明符),少用長(zhǎng)整型參數(shù)(%ld、%lu、%lx和%lX格式說(shuō)明符),至于浮點(diǎn)型的參數(shù)(%f)則盡量不要使用,其它C編譯器也一樣。在其它條件不變的情況下,使用%f參數(shù),會(huì)使生成的代碼的數(shù)量增加很多,執(zhí)行速度降低。

      4、使用自加、自減指令
            通常使用自加、自減指令和復(fù)合賦值表達(dá)式(如a-=1及a+=1等)都能夠生成高質(zhì)量的程序代碼,編譯器通常都能夠生成inc和dec之類(lèi)的指令,而使用 a=a+1或a=a-1之類(lèi)的指令,有很多C編譯器都會(huì)生成二到三個(gè)字節(jié)的指令。在AVR單片適用的ICCAVR、GCCAVR、IAR等C編譯器以上幾種書(shū)寫(xiě)方式生成的代碼是一樣的,也能夠生成高質(zhì)量的inc和dec之類(lèi)的的代碼。

      5、減少運(yùn)算的強(qiáng)度
            可以使用運(yùn)算量小但功能相同的表達(dá)式替換原來(lái)復(fù)雜的的表達(dá)式。如下:
      (1)、求余運(yùn)算。
              a=a%8;
      可以改為:
              a=a&7;

      說(shuō)明:位操作只需一個(gè)指令周期即可完成,而大部分的C編譯器的“%”運(yùn)算均是調(diào)用子程序來(lái)完成,代碼長(zhǎng)、執(zhí)行速度慢。通常,只要求是求2n方的余數(shù),均可使用位操作的方法來(lái)代替。

      (2)、平方運(yùn)算
              a=pow(a,2.0);
      可以改為:
              a=a*a;

      說(shuō)明:在有內(nèi)置硬件乘法器的單片機(jī)中(如51系列),乘法運(yùn)算比求平方運(yùn)算快得多,因?yàn)楦↑c(diǎn)數(shù)的求平方是通過(guò)調(diào)用子程序來(lái)實(shí)現(xiàn)的,在自帶硬件乘法器的AVR 單片機(jī)中,如ATMega163中,乘法運(yùn)算只需2個(gè)時(shí)鐘周期就可以完成。既使是在沒(méi)有內(nèi)置硬件乘法器的AVR單片機(jī)中,乘法運(yùn)算的子程序比平方運(yùn)算的子程序代碼短,執(zhí)行速度快。

      如果是求3次方,如:
              a=pow(a,3.0);
      更改為:
              a=a*a*a;
      則效率的改善更明顯。

      (3)、用移位實(shí)現(xiàn)乘除法運(yùn)算
              a=a*4;
              b=b/4;
      可以改為:
              a=a<<2;
              b=b>>2;

      說(shuō)明:通常如果需要乘以或除以2n,都可以用移位的方法代替。在ICCAVR中,如果乘以2n,都可以生成左移的代碼,而乘以其它的整數(shù)或除以任何數(shù),均調(diào)用乘除法子程序。用移位的方法得到代碼比調(diào)用乘除法子程序生成的代碼效率高。實(shí)際上,只要是乘以或除以一個(gè)整數(shù),均可以用移位的方法得到結(jié)果,如:
              a=a*9
      可以改為:
              a=(a<<3)+a

      6、循環(huán)
      (1)、循環(huán)語(yǔ)
            對(duì)于一些不需要循環(huán)變量參加運(yùn)算的任務(wù)可以把它們放到循環(huán)外面,這里的任務(wù)包括表達(dá)式、函數(shù)的調(diào)用、指針運(yùn)算、數(shù)組訪問(wèn)等,應(yīng)該將沒(méi)有必要執(zhí)行多次的操作全部集合在一起,放到一個(gè)init的初始化程序中進(jìn)行。

      (2)、延時(shí)函數(shù):
      通常使用的延時(shí)函數(shù)均采用自加的形式:
              void delay (void)
              {
      unsigned int i;
              for (i=0;i<1000;i++)
              ;
              }
      將其改為自減延時(shí)函數(shù):
              void delay (void)
              {
      unsigned int i;
                  for (i=1000;i>0;i--)
              ;
              }

            兩個(gè)函數(shù)的延時(shí)效果相似,但幾乎所有的C編譯對(duì)后一種函數(shù)生成的代碼均比前一種代碼少1~3個(gè)字節(jié),因?yàn)閹缀跛械腗CU均有為0轉(zhuǎn)移的指令,采用后一種方式能夠生成這類(lèi)指令。在使用while循環(huán)時(shí)也一樣,使用自減指令控制循環(huán)會(huì)比使用自加指令控制循環(huán)生成的代碼更少1~3個(gè)字母。但是在循環(huán)中有通過(guò)循環(huán)變量“i”讀寫(xiě)數(shù)組的指令時(shí),使用預(yù)減循環(huán)時(shí)有可能使數(shù)組超界,要引起注意。

      (3)while循環(huán)和do…while循環(huán)
      用while循環(huán)時(shí)有以下兩種循環(huán)形式:
      unsigned int i;
              i=0;
              while (i<1000)
              {
                  i++;
              //用戶(hù)程序
              }
      或:
      unsigned int i;
              i=1000;
              do
              i--;
              //用戶(hù)程序
              while (i>0);
            在這兩種循環(huán)中,使用do…while循環(huán)編譯后生成的代碼的長(zhǎng)度短于while循環(huán)。

      7、查表
            在程序中一般不進(jìn)行非常復(fù)雜的運(yùn)算,如浮點(diǎn)數(shù)的乘除及開(kāi)方等,以及一些復(fù)雜的數(shù)學(xué)模型的插補(bǔ)運(yùn)算,對(duì)這些即消耗時(shí)間又消費(fèi)資源的運(yùn)算,應(yīng)盡量使用查表的方式,并且將數(shù)據(jù)表置于程序存儲(chǔ)區(qū)。如果直接生成所需的表比較困難,也盡量在啟了,減少了程序執(zhí)行過(guò)程中重復(fù)計(jì)算的工作量。

      8、其它
      比如使用在線匯編及將字符串和一些常量保存在程序存儲(chǔ)器中,均有利于優(yōu)化


      嵌入式實(shí)時(shí)程序設(shè)計(jì)中C/C++代碼的優(yōu)化

      1 引言

            計(jì)算機(jī)技術(shù)和信息技術(shù)的高速發(fā)展的今天,計(jì)算機(jī)和計(jì)算機(jī)技術(shù)大量應(yīng)用在人們的日常生活中,嵌入式計(jì)算機(jī)也得到了廣泛的應(yīng)用。 嵌入式計(jì)算機(jī)是指完成一種或多種特定功能的計(jì)算機(jī)系統(tǒng),是軟硬件的緊密結(jié)合體。具有軟件代碼小、高度自動(dòng)化、響應(yīng)速度快等特點(diǎn)。 特別適合于要求實(shí)時(shí)和多任務(wù)的應(yīng)用體系。嵌入式實(shí)時(shí)系統(tǒng)是目前蓬勃發(fā)展的行業(yè)之一。      但是,實(shí)時(shí)嵌入式系統(tǒng)的特點(diǎn)使得其軟件受時(shí)間和空間的嚴(yán)格限制,加上運(yùn)行環(huán)境復(fù)雜,使得嵌入式系統(tǒng)軟件的開(kāi)發(fā)變得異常困難。 為了設(shè)計(jì)一個(gè)滿(mǎn)足功能、性能和死線要求的系統(tǒng),為了開(kāi)發(fā)出安全可靠的高性能嵌入式系統(tǒng),開(kāi)發(fā)語(yǔ)言的選擇十分重要。 
      2 嵌入式實(shí)時(shí)程序設(shè)計(jì)中語(yǔ)言的選擇

          
      隨著嵌入式系統(tǒng)應(yīng)用范圍的不斷擴(kuò)大和嵌入式實(shí)時(shí)操作系統(tǒng)RTOS(Real Time Operating System)的廣泛使用,高級(jí)語(yǔ)言編程已是嵌入式系統(tǒng)設(shè)計(jì)的必然趨勢(shì)。因?yàn)閰R編語(yǔ)言和具體的微處理器的硬件結(jié)構(gòu)密切相關(guān),移植性較差,既不宜在復(fù)雜系統(tǒng)中使用,又不便于實(shí)現(xiàn)軟件重用;而高級(jí)語(yǔ)言具有良好的通用性和豐富的軟件支持,便于推廣、易于維護(hù),因此高級(jí)語(yǔ)言編程具有許多優(yōu)勢(shì)。目前,在嵌入式系統(tǒng)開(kāi)發(fā)過(guò)程中使用的語(yǔ)言種類(lèi)很多,但僅有少數(shù)幾種語(yǔ)言得到了比較廣泛的應(yīng)用。其中C和C++是應(yīng)用最廣泛的。C++在支持現(xiàn)代軟件工程、 OOP(Object Oriented Programming,面向?qū)ο蟮某绦蛟O(shè)計(jì))、結(jié)構(gòu)化等方面對(duì)C進(jìn)行了卓有成效的改進(jìn),但在程序代碼容量、執(zhí)行速度、程序復(fù)雜程度等方面比C語(yǔ)言程序性能差一些。由于C語(yǔ)言既有低級(jí)語(yǔ)言的直接控制硬件的能力,又有高級(jí)語(yǔ)言的靈活性,是目前在嵌入式系統(tǒng)中應(yīng)用最廣泛的編程語(yǔ)言。隨著網(wǎng)絡(luò)技術(shù)和嵌入式技術(shù)的不斷發(fā)展,Java的應(yīng)用也得到廣泛應(yīng)用。

      3 C/C++代碼在實(shí)時(shí)程序設(shè)計(jì)中的優(yōu)化

          
      雖然使軟件正確是一個(gè)工程合乎邏輯的最后一個(gè)步驟,但是在嵌入式的系統(tǒng)開(kāi)發(fā)中,情況并不總是這樣的。出于對(duì)低價(jià)產(chǎn)品的需求, 硬件的設(shè)計(jì)者需要提供剛好足夠的存儲(chǔ)器和完成工作的處理能力。所以在嵌入式軟件設(shè)計(jì)的最后一個(gè)階段則變成了對(duì)代碼的優(yōu)化。   

      現(xiàn)代的C和C++編譯器都提供了一定程度上的代碼優(yōu)化。然而,大部分由編譯器執(zhí)行的優(yōu)化僅涉及執(zhí)行速度和代碼大小的一個(gè)平衡。你的程序能夠變得更快或者更小,但是不可能又變快又變小。經(jīng)過(guò)本人在嵌入式系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)過(guò)程中實(shí)踐,下面介紹幾種簡(jiǎn)單且行之有效的C/C++代碼的優(yōu)化方法。

            (1) Inline函數(shù)

            在C++中,關(guān)鍵字Inline可以被加入到任何函數(shù)的聲明中。這個(gè)關(guān)鍵字請(qǐng)求編譯器用函數(shù)內(nèi)部的代碼替換所有對(duì)于指出的函數(shù)的調(diào)用。這樣做在兩個(gè)方面快于函數(shù)調(diào)用。這樣做在兩個(gè)方面快于函數(shù)調(diào)用:第一,省去了調(diào)用指令需要的執(zhí)行時(shí)間;第二,省去了傳遞變?cè)蛡鬟f過(guò)程需要的時(shí)間。但是使用這種方法在優(yōu)化程序速度的同時(shí),程序長(zhǎng)度變大了,因此需要更多的ROM。使用這種優(yōu)化在Inline函數(shù)頻繁調(diào)用并且只包含幾行代碼的時(shí)候是最有效的。 
            (2)用指針代替數(shù)組

            在許多種情況下,可以用指針運(yùn)算代替數(shù)組索引,這樣做常常能產(chǎn)生又快又短的代碼。與數(shù)組索引相比,指針一般能使代碼速度更快,占用空間更少。使用多維數(shù)組時(shí)差異更明顯。下面的代碼作用是相同的,但是效率不一樣。 
            數(shù)組索引                  指針運(yùn)算 
            For(;;){                  p=array 
            A=array[t++];            for(;;){ 
                                        a=*(p++); 
            ......                      ...... 
            }                        }

            指針?lè)椒ǖ膬?yōu)點(diǎn)是,array的地址每次裝入地址p后,在每次循環(huán)中只需對(duì)p增量操作。在數(shù)組索引方法中,每次循環(huán)中都必須進(jìn)行基于t值求數(shù)組下標(biāo)的復(fù)雜運(yùn)算。 
            (3)不定義不使用的返回值

            function函數(shù)定義并不知道函數(shù)返回值是否被使用,假如返回值從來(lái)不會(huì)被用到,應(yīng)該使用void來(lái)明確聲明函數(shù)不返回任何值。

            (4)手動(dòng)編寫(xiě)匯編

            在嵌入式軟件開(kāi)發(fā)中,一些軟件模塊最好用匯編語(yǔ)言來(lái)寫(xiě),這可以使程序更加有效。雖然C/C++編譯器對(duì)代碼進(jìn)行了優(yōu)化,但是適當(dāng)?shù)氖褂脙?nèi)聯(lián)匯編指令可以有效的提高整個(gè)系統(tǒng)運(yùn)行的效率。 
            (5)使用寄存器變量

            在聲明局部變量的時(shí)候可以使用register關(guān)鍵字。這就使得編譯器把變量放入一個(gè)多用途的寄存器中,而不是在堆棧中,合理使用這種方法可以提高執(zhí)行速度。函數(shù)調(diào)用越是頻繁,越是可能提高代碼的速度。 
            (6)使用增量和減量操作符

            在使用到加一和減一操作時(shí)盡量使用增量和減量操作符,因?yàn)樵隽糠Z(yǔ)句比賦值語(yǔ)句更快,原因在于對(duì)大多數(shù)CPU來(lái)說(shuō),對(duì)內(nèi)存字的增、 減量操作不必明顯地使用取內(nèi)存和寫(xiě)內(nèi)存的指令,比如下面這條語(yǔ)句: 
            x=x+1; 
            模仿大多數(shù)微機(jī)匯編語(yǔ)言為例,產(chǎn)生的代碼類(lèi)似于: 
            move A,x        ;把x從內(nèi)存取出存入累加器A 
            add A,1        ;累加器A加1 
            store x        ;把新值存回x

            如果使用增量操作符,生成的代碼如下: 
            incr x          ;x加1 
            顯然,不用取指令和存指令,增、減量操作執(zhí)行的速度加快,同時(shí)長(zhǎng)度也縮短了。

            (7)減少函數(shù)調(diào)用參數(shù)

            使用全局變量比函數(shù)傳遞參數(shù)更加有效率。這樣做去除了函數(shù)調(diào)用參數(shù)入棧和函數(shù)完成后參數(shù)出棧所需要的時(shí)間。然而決定使用全局變量會(huì)影響程序的模塊化和重入,故要慎重使用。 
            (8)Switch語(yǔ)句中根據(jù)發(fā)生頻率來(lái)進(jìn)行case排序

            switch語(yǔ)句是一個(gè)普通的編程技術(shù),編譯器會(huì)產(chǎn)生if-else-if的嵌套代碼,并按照順序進(jìn)行比較,發(fā)現(xiàn)匹配時(shí),就跳轉(zhuǎn)到滿(mǎn)足條件的語(yǔ)句執(zhí)行。使用時(shí)需要注意。每一個(gè)由機(jī)器語(yǔ)言實(shí)現(xiàn)的測(cè)試和跳轉(zhuǎn)僅僅是為了決定下一步要做什么,就把寶貴的處理器時(shí)間耗盡。為了提高速度,沒(méi)法把具體的情況按照它們發(fā)生的相對(duì)頻率排序。換句話說(shuō),把最可能發(fā)生的情況放在第一位,最不可能的情況放在最后。 
            (9)將大的switch語(yǔ)句轉(zhuǎn)為嵌套switch語(yǔ)句

            當(dāng)switch語(yǔ)句中的case標(biāo)號(hào)很多時(shí),為了減少比較的次數(shù),明智的做法是把大switch語(yǔ)句轉(zhuǎn)為嵌套switch語(yǔ)句。把發(fā)生頻率高的case 標(biāo)號(hào)放在一個(gè)switch語(yǔ)句中,并且是嵌套switch語(yǔ)句的最外層,發(fā)生相對(duì)頻率相對(duì)低的case標(biāo)號(hào)放在另一個(gè)switch語(yǔ)句中。比如,下面的程序段把相對(duì)發(fā)生頻率低的情況放在缺省的case標(biāo)號(hào)內(nèi)。          pMsg=ReceiveMessage(); 
                switch (pMsg->type) 
                { 
                case FREQUENT_MSG1: 
                handleFrequentMsg(); 
                break; 
                case FREQUENT_MSG2: 
                handleFrequentMsg2(); 
                break; 
                ...... 
                case FREQUENT_MSGn: 
                handleFrequentMsgn(); 
                break; 
                default:                        //嵌套部分用來(lái)處理不經(jīng)常發(fā)生的消息 
                switch (pMsg->type) 
                { 
                case INFREQUENT_MSG1: 
                handleInfrequentMsg1(); 
                break; 
                case INFREQUENT_MSG2: 
                handleInfrequentMsg

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多