方法A:通常的方法。
#定義?萊恩。32
夏爾?string1?[LEN];
memset?(string1,0,LEN);
strcpy?(string1,“這個?是嗎?答?舉例!!");
方法b:
const?夏爾?string2[LEN]?=“這個?是嗎?答?例子!”;
夏爾?*?CP;
cp?=?string2?;使用時可以用指針直接操作。
從上面的例子可以看出,A和B的效率是不可比的。同樣的存儲空間,B可以直接用指針操作,而A需要調用兩個字符函數來完成。b的缺點是靈活性不如A,當壹個字符串的內容需要頻繁改變時,A的靈活性更好;如果采用方法B,需要預存很多字符串,占用大量內存,但是實現了程序執行的高效率。
如果系統的實時性要求很高,還有點內存的話,那麽我推薦妳用這壹招。
第二招:用宏代替函數。這也是第壹招的變體。函數和宏的區別在於,宏占用大量空間,而函數占用時間。妳需要知道的是,函數調用使用系統的堆棧來保存數據。如果編譯器中有堆棧檢查選項,壹些匯編語句會被嵌入到函數的頭部來檢查當前的堆棧。同時,函數調用時CPU還要保存和還原當前場景,進行堆棧壓入和堆棧彈回操作,所以函數調用需要壹定的CPU時間。宏沒有這個問題。宏只是作為預寫好的代碼嵌入到當前程序中,不會產生函數調用,所以只是占用空間,尤其是頻繁調用同壹個宏的時候。
例子如下:
方法c:
#定義?bwMCDR2_ADDRESS?四
#定義?bsMCDR2_ADDRESS?17
int?BIT_MASK(int?__bf)
{
回歸?((1U?& lt& lt?(bw?##?__bf))?-?1)& lt;& lt?(bs?##?_ _ BF);
}
作廢?SET_BITS(int?_ _夏令時,
int?__bf,?int?__val)
{
__dst?=?((__dst)?& amp?~(BIT_MASK(__bf))?|
(((__val)?& lt& lt?(bs?##?__bf))
& amp?(位掩碼(__bf))))
}
SET_BITS(MCDR2,MCDR2_ADDRESS,register number);方法d:
#定義?bwMCDR2_ADDRESS?四
#定義?bsMCDR2_ADDRESS?17
#定義?bmMCDR2_ADDRESS?位掩碼(MCDR2地址)
#定義?位掩碼(__bf)
(((1U?& lt& lt?(bw?##?__bf))?-?1)
& lt& lt?(bs?##?__bf))
#定義?SET_BITS(__dst,?__bf,?__val)
((__dst)?=?((__dst)?& amp?~(位掩碼(__bf)))
|
(((__val)?& lt& lt?(bs?##?__bf))
& amp?(位掩碼(__bf))))
SET_BITS(MCDR2,MCDR2_ADDRESS,
註冊號碼);d方法是我見過最好的集合運算函數,是arm公司源代碼的壹部分。它僅用三行代碼就實現了許多功能,幾乎涵蓋了所有的位操作功能。方法C是它的變種,味道需要仔細了解。
第三招:用數學方法解題。
現在我們推導高效C語言寫作的第二招——用數學方法解決問題。數學是計算機之母。沒有數學的基礎和底子,就沒有計算機的發展。所以在編寫程序時,采用壹些數學方法,會使程序的執行效率提高幾個數量級。比如求1~100的和。
方法e:
int?我?,?j;
為了什麽?(我?=?1?;我& lt=100;?我?++)
{
j?+=?我;
}方法f
int?我;
我?=?(100?*?(1+100))?/?這個例子是我印象最深的壹個數學用例。是我的電腦啟蒙老師測試的。那時候我才小學三年級。可惜我不知道怎麽用公式N×(N+1)/ 2來解決這個問題。方法E已經循環了100次解題,也就是說至少用了100次賦值,100次判斷,200次加法(I和J);方法F僅使用1次加法、1次乘法和1次除法。效果不言而喻。所以我現在編程的時候,更多考慮的是尋找規律,發揮數學的力量,提高程序的效率。
第四招:用位運算用位運算。減少除法和模運算。在計算機程序中,數據位是可以操作的最小數據單位。理論上所有的運算和操作都可以通過“位運算”來完成。壹般的位操作是用來控制硬件或者做數據轉換的,但是靈活的位操作可以有效的提高程序運行的效率。例子如下:
方法g
int?I,J;
我?=?257?/8;
j?=?456?%?32;方法h
int?I,J;
我?=?257?& gt& gt3;
j?=?456?-?(456?& gt& gt?4?& lt& lt?4);從字面上看,H好像比G麻煩很多,但是仔細看生成的匯編代碼就會明白,G方法調用的是基本的模函數和除法函數,既有函數調用,也有很多匯編代碼和寄存器。方法H只是幾個相關的程序集,代碼更簡單高效。當然由於編譯器的不同,效率差距可能不大,但是從我目前遇到的MS C,arm C來看,效率差距還是不小的。
對於以2的指數冪為“*”、“/”或“%”因子的數學運算,轉化為移位運算”
c語言的位運算不僅提高了運算效率,而且廣泛應用於嵌入式系統的編程中。),或者(|),而不是(~)運算,這和嵌入式系統的編程特點有很大關系。我們通常需要設置硬件寄存器的位。例如,我們將AM186ER處理器的中斷屏蔽控制寄存器的最低6位設置為0(中斷2)。最常見的方式是:
#define INT_I2_MASK 0x0040
w temp = in word(INT _ MASK);
outword(INT_MASK,wTemp & amp~ INT _ I2 _ MASK);
將該位設置為1的方法是:
#define INT_I2_MASK 0x0040
w temp = in word(INT _ MASK);
outword(INT_MASK,w temp | INT _ I2 _ MASK);
判斷該位是否為1的方法是:
#define INT_I2_MASK 0x0040
w temp = in word(INT _ MASK);
if(wTemp & amp;INT_I2_MASK)
{
.../*這個位是1 */
}
使用這壹招需要註意的是CPU不同帶來的問題。比如在PC上用這種方式編寫的程序,在PC上調試,移植到16位的計算機平臺上可能會產生代碼隱患。所以這壹招只能在壹定的先進技術基礎上使用。
第五招:匯編內嵌在熟悉匯編語言的人眼裏,用C語言寫的程序都是垃圾。“這種說法雖然有點偏激,但有其道理。匯編語言是效率最高的計算機語言,但是用它寫操作系統是不可能的吧?因此,為了獲得程序的高效率,我們不得不采用靈活的方法——嵌入式匯編和混合編程。在線匯編主要用在嵌入式C程序中,也就是將_asm{}嵌入式匯編語句直接插入到C程序中。
例如,將數組1賦給數組2,並要求每個字節都匹配。
char string1[1024],string 2[1024];
方法壹
int I;
for(I = 0;我& lt1024;I++)
*(string2 + I) = *(string1 + I)
方法j
#ifdef _PC_
int I;
for(I = 0;我& lt1024;I++)
*(string 2+I)= *(string 1+I);
#否則
#ifdef _arm_
__asm
{
MOV R0,字符串1
MOV R1,字符串2
MOV R2,#0
循環:
LDMIA R0!,[R3-R11]
STMIA R1!,[R3-R11]
添加R2,R2,#8
CMP R2,#400
BNE環路
}
#endif
再舉壹個例子:
/*將兩個輸入參數的值相加,並將結果存儲在另壹個全局變量中*/
int結果;
void Add(long a,long *b)
{
_asm
{
MOV阿克斯
MOV·BX灣
添加AX,[BX]
MOV結果,AX
}
}
方法壹是最常用的方法,使用1024個循環;方法J是根據不同的平臺來區分的。在arm平臺下,用嵌入式匯編完成同樣的操作只需要128個周期。這裏有些朋友會說,為什麽不用標準的內存復制功能呢?這是因為源數據可能包含數據為0的字節,在這種情況下,標準庫函數將提前結束,不會完成我們要求的操作。該例程通常應用於LCD數據的復制過程。根據不同的CPU,巧妙地使用相應的嵌入式匯編可以大大提高程序執行的效率。
雖然是殺手鐧技能,但是輕易使用就會付出沈重的代價。這是因為嵌入式匯編的使用限制了程序的可移植性,使得程序在不同平臺上移植的過程,臥虎藏龍,險象環生!同時,這壹招也違背了現代軟件工程的思想,只有在絕對必要的情況下才能采用。
第六個技巧是使用寄存器變量。當壹個變量被頻繁讀寫時,需要反復訪問內存,從而花費大量的訪問時間。為此,C語言提供了壹個變量,即寄存器變量。該變量存儲在CPU的寄存器中。使用時,可以直接從寄存器中讀寫,無需訪問存儲器,提高了效率。寄存器變量的說明符是register。無論是循環次數多的循環控制變量,還是循環中重復使用的變量,都可以定義為寄存器變量,循環次數是應用寄存器變量的最佳候選。
(1)只有局部自動變量和形參可以定義為寄存器變量。因為寄存器變量屬於動態存儲方式,任何需要靜態存儲方式的量都不能定義為寄存器變量,包括:模塊間全局變量、模塊內全局變量和局部靜態變量;
(2) register是壹個“建議的”關鍵字,意思是程序建議把變量放在寄存器中,但最後可能因為條件不滿足,變量沒有變成寄存器變量,而是放在了內存中,但編譯器沒有報錯(C++語言中還有壹個“建議的”關鍵字:inline)。
下面是壹個使用寄存器變量的例子:
/*求1+2+3+的值...+n */
字加法(字節n)
{
寄存器I,s = 0;
for(I = 1;我& lt= n;i++)
{
s = s+I;
}
返回s;
}
這個程序循環N次,I和S是經常使用的,所以可以定義為寄存器變量。
第七招:使用硬件特性首先要了解CPU對各種內存的訪問速度,基本上是:
CPU的內部ram >;外部同步RAM >外部異步RAM >;閃存/只讀存儲器
對於已經燒錄在FLASH或者ROM中的程序代碼,我們可以讓CPU直接讀取代碼並執行,但這通常不是壹個好辦法。我們最好在系統啟動後,將FLASH或ROM中的目標代碼復制到RAM中,然後執行,以提高取指令速度。
對於UART等設備,內部有壹定容量的接收緩沖區,盡量在緩沖區滿了之後中斷CPU。例如,當計算機終端通過RS-232向目標機傳輸數據時,設置UART僅在接收到壹個字節後中斷CPU是不合適的,這樣會不必要地浪費中斷處理時間;
如果壹個設備可以通過DMA讀取,則采用DMA讀取。當讀取目標包含的存儲信息量較大,數據傳輸的基本單位是塊,傳輸的數據直接從設備發送到內存(或者反之亦然)時,DMA讀取效率更高。與中斷驅動方式相比,DMA方式減少了CPU對外設的幹預,進壹步提高了CPU與外設並行操作的程度。
我就是這樣總結出如何優化C代碼的。