教你如何利用C語言來優化程式?

程式進行優化,通常是指優化程式程式碼或程式履行速度。優化程式碼和優化速度實踐上是一個予盾的共同,通常是優化了程式碼的尺度,就會帶來履行時刻的新增,若是優化了程式的履行速度,通常會帶來程式碼新增的副作用,很難魚與熊掌兼得,只能在描繪時把握一個平衡點。

一、程式佈局的優化 1、程式的書寫佈局儘管書寫格局並不會影響生成的程式碼質量,但是在實踐編寫程式時仍是大概尊循必定的書寫規矩,一個書寫明晰、明晰的程式,有利於今後的保護。在書寫程式時,特別是關於While、for、do…while、if…elst、switch…case等句子或這些句子巢狀組合時,應選用“縮格”的書寫辦法,

2、識別符號程式中運用的使用者識別符號除要遵從識別符號的命名規矩以外,通常不要用代數符號(如a、b、x1、y1)作為變數名,應挑選具有有關意義的英文單詞(或縮寫)或漢語拼音作為識別符號,以新增程式的可讀性,如:count、number1、red、work等。

3、程式佈局C言語是一種高檔程式描繪言語,供給了非常齊備的規範化流程操控佈局。因而在選用C言語描繪微控制器運用體系程式時,首要要注意儘可能選用佈局化的程式描繪辦法,這樣可使整個運用體系程式佈局明晰,便於除錯和保護。於一個較大的運用程式,通常將整個程式按功用分紅若干個模組,不相同模組完結不相同的功用。各個模組可以別離編寫,乃至還可以由不相同的程式設計師編寫,通常單個模組完結的功用較為簡略,描繪和除錯也相對簡單一些。在C言語中,一個函式就可以認為是一個模組。所謂程式模組化,不僅是要將整個程式劃分紅若干個功用模組,更重要的是,還大概注意堅持各個模組之間變數的相對獨立性,即堅持模組的獨立性,儘量少運用全域性變數等。關於一些常用的功用模組,還可以封裝為一個運用程式庫,以便需求時可以直接呼叫。但是在運用模組化時,若是將模組分紅太細太小,又會致使程式的履行功率變低(進入和退出一個函式時保護和康復暫存器佔用了一些時刻)。

4、界說常數在程式化描繪過程中,關於常常運用的一些常數,若是將它直接寫到程式中去,一旦常數的數值發生變化,就有必要逐個找出程式中一切的常數,並逐個進行修正,這樣必然會下降程式的可保護性。因而,應儘量當選用預處理指令辦法來界說常數,而且還可以防止輸入過錯。

5、削減判別句子可以運用條件編譯(ifdef)的當地就運用條件編譯而不運用if句子,有利於削減編譯生成的程式碼的長度,可以不必判別句子則少用判別用句子。

6、表示式關於一個表示式中各種運算履行的優先次序不太清晰或簡單混雜的當地,應當選用圓括號清晰指定它們的優先次序。一個表示式通常不能寫得太雜亂,若是表示式太雜亂,時刻久了今後,自個也不簡單看得懂,不利於今後的保護。

7、函式關於程式中的函式,在運用之前,應對函式的型別進行闡明,對函式型別的闡明有必要確保它與本來界說的函式型別共同,關於沒有引數和沒有返回值型別的函式應加上“void”闡明。若是果需求縮短程式碼的長度,可以將程式中一些公共的程式段界說為函式,在Keil中的高檔別優化即是這樣的。若是需求縮短程式的履行時刻,在程式除錯完畢後,將有些函式用巨集界說來替代。注意,大概在程式除錯完畢後再界說巨集,由於大多數編譯體系在巨集開啟之後才會報錯,這樣會新增排錯的難度。

8、儘量少用全域性變數,多用區域性變數。由於全域性變數是放在資料儲存器中,界說一個全域性變數,MCU就少一個可以運用的資料儲存器空間,若是界說了太多的全域性變數,會致使編譯器無滿足的記憶體可以分配。而區域性變數大多定坐落MCU內部的暫存器中,在絕大多數MCU中,運用暫存器操作速度比資料儲存器快,指令也更多更靈敏,有利於生成質量更高的程式碼,而且區域性變數所的佔用的暫存器和資料儲存器在不相同的模組中可以重複運用。

9、設定適宜的編譯程式選項許多編譯程式有幾種不相同的優化選項,在運用前應瞭解各優化選項的意義,然後選用最適宜的一種優化辦法。通常情況下一旦選用最高檔優化,編譯程式會近乎病態地尋求程式碼優化,可能會影響程式的正確性,致使程式運轉犯錯。因而應瞭解所運用的編譯器,應曉得哪些引數在優化時會受到影響,哪些引數不會受到影響。在ICCAVR中,有“Default”和“Enable Code Compression”兩個優化選項。在CodeVisionAVR中,“Tiny”和“small”兩種記憶體方法。在IAR中,共有7種不相同的記憶體方法選項。在GCCAVR中優化選項更多,一不小心更簡單選到不恰當的選項。

二、程式碼的優化 1、挑選適宜的演算法和資料佈局大概瞭解演算法言語,曉得各種演算法的優缺點,詳細材料請拜見相應的參考材料,有許多核算機書本上都有介紹。將對比慢的次序查詢法用較快的二分查詢或亂序查詢法替代,刺進排序或氣泡排序法用疾速排序、兼併排序或根排序替代,都可以大大提高程式履行的功率。.挑選一種適宜的資料佈局也很重要,比方你在成堆隨機寄存的數中運用了許多的刺進和刪去指令,那運用連結串列要快得多。陣列與指標句子具有非常暗碼的聯絡,通常來說,指標對比靈敏簡練,而陣列則對比直觀,簡單瞭解。關於大有些的編譯器,運用指標比運用陣列生成的程式碼更短,履行功率更高。但是在Keil中則相反,運用陣列比運用的指標生成的程式碼更短。。

3、運用盡量小的資料型別可以運用字元型(char)界說的變數,就不要運用整型(int)變數來界說;可以運用整型變數界說的變數就不要用長整型(long int),能不運用浮點型(float)變數就不要運用浮點型變數。當然,在界說變數後不要超越變數的作用規模,若是超越變數的規模賦值,C編譯器並不報錯,但程式運轉成果卻錯了,而且這樣的過錯很難發現。在ICCAVR中,可以在Options中設定運用printf引數,儘量運用根本型引數(%c、%d、%x、%X、%u和%s格局闡明符),少用長整型引數(%ld、%lu、%lx和%lX格局闡明符),至於浮點型的引數(%f)則儘量不要運用,其它C編譯器也相同。在其它條件不變的情況下,運用%f引數,會使生成的程式碼的數量新增許多,履行速度下降。

4、運用自加、自減指令通常運用自加、自減指令和複合賦值表示式(如a-=1及a+=1等)都可以生成高質量的程式程式碼,編譯器通常都可以生成inc和dec之類的指令,而運用a=a+1或a=a-1之類的指令,有許多C編譯器都會生成二到三個位元組的指令。在AVR單片適用的ICCAVR、GCCAVR、IAR等C編譯器以上幾種書寫辦法生成的程式碼是相同的,也可以生成高質量的inc和dec之類的的程式碼。

5、削減運算的強度可以運用運算量小但功用相同的表示式更換本來雜亂的的表示式。如下:

(1)、求餘運算。 a=a%8;可以改為: a=a&7;闡明:位操作只需一個指令週期即可完結,而大有些的C編譯器的“%”運算均是呼叫子程式來完結,程式碼長、履行速度慢。通常,只需求是求2n方的餘數,均可運用位操作的辦法來替代。

(2)、平方運算 a=pow(a,2.0);可以改為: a=a*a;闡明:在有內建硬體乘法器的微控制器中(如51系列),乘法運算比求平方運算快得多,由於浮點數的求平方是經過呼叫子程式來完結的,在自帶硬體乘法器的AVR微控制器中,如ATMega163中,乘法運算只需2個時鐘週期就可以完結。既使是在沒有內建硬體乘法器的AVR微控制器中,乘法運算的子程式比平方運算的子程式程式碼短,履行速度快。

若是是求3次方,如: a=pow(a,3.0);更改為: a=a*a*a;則功率的改進更顯著。

(3)、用移位完結乘除法運算 a=a*4; b=b/4;可以改為: a=a<<2; b=b>>2;闡明:通常若是需求乘以或除以2n,都可以用移位的辦法替代。在ICCAVR中,若是乘以2n,都可以生成左移的程式碼,而乘以其它的整數或除以任何數,均呼叫乘除法子程式。用移位的辦法得到程式碼比呼叫乘除法子程式生成的程式碼功率高。實踐上,只需是乘以或除以一個整數,均可以用移位的辦法得到成果,如: a=a*9可以改為: a=(a<<3)+a

6、迴圈(1)、迴圈語 關於一些不需求迴圈變數參與運算的使命可以把它們放到迴圈外面,這裡的使命包含表示式、函式的呼叫、指標運算、陣列拜訪等,大概將沒有必要履行屢次的操作悉數調集在一起,放到一個init的初始化程式中進行。

(2)、延時函式: 通常運用的延時函式均選用自加的辦法: void delay (void) {unsigned int i; for (i=0;i<1000;i++) ; }將其改為自減延時函式: void delay (void) {unsigned int i; for (i=1000;i>0;i--) ; }兩個函式的延時作用類似,但簡直一切的C編譯對後一種函式生成的程式碼均比前一種程式碼少1~3個位元組,由於簡直一切的MCU均有為0搬運的指令,選用後一種辦法可以生成這類指令。在運用while迴圈時也相同,運用自減指令操控迴圈會比運用自加指令操控迴圈生成的程式碼更少1~3個字母。但是在迴圈中有經過迴圈變數“i”讀寫陣列的指令時,運用預減迴圈時有可能使陣列超界,要導致注意。

(3)while迴圈和do…while迴圈用while迴圈時有以下兩種迴圈辦法:unsigned int i; i=0; while (i<1000) { i++; //使用者程式 }或:unsigned int i; i=1000; do i--; //使用者程式 while (i>0);在這兩種迴圈中,運用do…while迴圈編譯後生成的程式碼的長度短於while迴圈。

7、查表在程式中通常不進行非常雜亂的運算,如浮點數的乘除及開方等,以及一些雜亂的數學模型的插補運算,對這些即耗費時刻又花費資源的運算,應儘量運用查表的辦法,而且將資料表置於程式儲存區。若是直接生成所需的表對比艱難,也儘量在啟動時先核算,然後在資料儲存器中生成所需的表,後以在程式運轉直接查表就可以了,削減了程式履行過程中重複核算的工作量。

8、其它比方運用線上彙編及將字串和一些常量儲存在程式儲存器中,均有利於優化

程式碼, 語言, 程式,
相關問題答案