針對(duì)嵌入式SoC應(yīng)用的C編程優(yōu)化
5. 使用本地變量替代全局變量
這是因?yàn)槿肿兞繒?huì)在整個(gè)程序的生命周期里面保留數(shù)值。編譯器必須認(rèn)為全局變量可能通過(guò)指針被訪問(wèn)??紤]下面的代碼:
int g;
void foo()
{
int i;
for (i=0; i100; i++){
fred(i,g);
}
}
理想情況下,g在每次fred循環(huán)時(shí)被加載一次,并且它的值將被傳遞到一個(gè)寄存器里面給fred函數(shù)使用。但是,編譯器不知道fred是否會(huì)修改g 的值。如果fred不會(huì)修改g的值,你應(yīng)該像下面一樣,使用本地變量。這樣做可以避免每次調(diào)用fred函數(shù)時(shí)加載g到一個(gè)寄存器里面。
int g;
void foo()
{
int i, local_g=g;
for (i=0; i100; i++){
fred(i,local_g);
}
}
6. 針對(duì)數(shù)據(jù)結(jié)構(gòu)使用正確的數(shù)據(jù)類(lèi)型
C編程人員對(duì)于數(shù)據(jù)類(lèi)型一般都會(huì)有他們習(xí)慣上的假設(shè),但是編譯器卻需要很謹(jǐn)慎地對(duì)待這些假設(shè)。比如,在幾乎所有現(xiàn)代的計(jì)算機(jī)架構(gòu)上,一個(gè) unsigned char使用8位表示從0到255。一個(gè)C程序會(huì)假設(shè)對(duì)值為255的unsigned char加1會(huì)使其變?yōu)?。而實(shí)際上,現(xiàn)代32位處理器是不會(huì)執(zhí)行上述的那種8位加法,而是進(jìn)行32位數(shù)值的加法。因此,如果一個(gè)unsigned char的本地變量進(jìn)行加法,編譯器必須使用多條指令進(jìn)行運(yùn)算以保證加法后的符號(hào)擴(kuò)展。因此,針對(duì)各種變量尤其是循環(huán)索引的變量,應(yīng)該盡量多的在可以的地方使用int型變量。
另外,許多嵌入式處理器有16位乘法指令,而缺少32位乘法指令。在這種情況下,32位乘法將被仿效執(zhí)行,一般情況下都是很慢的。如果數(shù)據(jù)被執(zhí)行乘法操作并且計(jì)算結(jié)果不會(huì)超過(guò)16位的精度,那么就使用short或者unsigned short變量。
7. 不要用不直接的調(diào)用
這是通過(guò)包含傳遞參數(shù)的函數(shù)指針的調(diào)用,因?yàn)槟菚?huì)產(chǎn)生不可預(yù)知的邊際效應(yīng)(比如修改全局變量),使得優(yōu)化難以進(jìn)行。
8. 編寫(xiě)返回?cái)?shù)值的函數(shù)而不是返回指針的函數(shù)
9. 傳遞變量時(shí)使用數(shù)值而不是指針或者全局變量
傳遞大結(jié)構(gòu)的數(shù)據(jù)時(shí),才使用指針。每個(gè)通過(guò)數(shù)值被傳遞的結(jié)構(gòu)都應(yīng)該在函數(shù)調(diào)用入口處被完全拷貝存儲(chǔ)過(guò)。
10. 使用變量的地址會(huì)使程序性能降低
因?yàn)楸镜刈兞康牡刂窌?huì)引起混淆,這如同全局變量一樣。
11. 用const聲明指針參數(shù)
如果函數(shù)體內(nèi)不會(huì)修改到指針指向的對(duì)象,就要用const聲明指針參數(shù),這樣可以讓編譯器避免不必要的反面假設(shè)。
12. 使用數(shù)組而不是指針,考慮下面通過(guò)指針訪問(wèn)數(shù)組的代碼
for (i=0; i100; i++)
*p++ = ...
在每次循環(huán)中,*p被賦值。這種對(duì)指針對(duì)象的賦值會(huì)阻礙優(yōu)化。某些情況下,指針指向它自己,那么這種賦值就會(huì)修改指針本身的值,這就會(huì)強(qiáng)迫編譯器每次循環(huán)都重新加載該指針。還有,編譯器不能確定這個(gè)指針不會(huì)被循環(huán)體以外的使用,所以每次循環(huán)外都要依據(jù)增量的數(shù)值更新該指針。因此,最好使用下面的代碼:
for (i=0; i100; i++)
p[i] = ...
linux操作系統(tǒng)文章專(zhuān)題:linux操作系統(tǒng)詳解(linux不再難懂)
評(píng)論