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