代碼之美,不僅在于為一個給定問題找到解決方案,而且還在代碼的簡單性、有效性、緊湊性和效率(記憶體)。代碼設計比實際執行更難 。是以,每一個程式員當用C語言程式設計時,都應該記着這些東西。本文向你介紹規範你的C代碼的10種方法。
0. 避免不必要的函數調用
考慮下面的2個函數:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
請注意 這兩個函數的功能相似。然而,第一個函數調用strlen()函數多次,而第二個函數隻調用函數strlen()一次。是以第二個函數性能明顯比第一個好。
注:在上述代碼中其實可以采用另外的方式來寫,效率更高
for (i=0;str[i];i++)
printf("%c",str[ i ] );
這樣str[i]為空自然就跳出了
1、避免不必要的記憶體引用這次我們再用2個例子來對比解釋:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
同樣,這兩個函數具有類似的功能。所不同的是在第一個函數( 1 for reading *num1 , 2 for reading *num2 and 2 for writing to *num1)有5個記憶體的引用,而在第二個函數是隻有2個記憶體引用(one for reading *num2 and one for writing to *num1)。現在你認為哪一個好些?
2、節約記憶體(記憶體對齊和填充的概念)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
假設一個字元需要1個位元組,short占用2個位元組和int需要4位元組的記憶體。起初,我們會認為上面定義的結構是相同的,是以占據相同數量的記憶體。然而,而str_1占用12個位元組,第二個結構隻需要8個位元組?這怎麼可能呢?
請注意,在第一個結構,3個不同的4個位元組被配置設定到三種資料類型,而在第二個結構的前4個自己char和short可以被采用,int可以采納在第二個的4個位元組邊界(一共8個位元組)。
3、使用無符号整數,而不是整數的,如果你知道的值将永遠是否定的。
有些處理器可以處理無符号的整數比有符号整數的運算速度要快。(這也是很好的實踐,幫助self-documenting代碼)。
4、在一個邏輯條件語句中常數項永遠在左側。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
使用“=”指派運算符,替代“==”相等運算符,這是個常見的輸入錯誤。 常數項放在左側,将産生一個編譯時錯誤,讓你輕松捕獲你的錯誤。注:“=”是指派運算符。 b = 1會設定變量b等于值1。 “==”相等運算符。如果左側等于右側,傳回true,否則傳回false。
5、在可能的情況下使用typedef替代macro。當然有時候你無法避免macro,但是typedef更好。
1 2 3 4 5 6 7 | |
在這個宏定義中,a是一個指向整數的指針,而b是隻有一個整數聲明。使用typedef a和b都是 整數的指針。
6、確定聲明和定義是靜态的,除非您希望從不同的檔案中調用該函數。
在同一檔案函數對其他函數可見,才稱之為靜态函數。它限制其他通路内部函數,如果我們希望從外界隐藏該函數。現在我們并不需要為内部函數建立頭檔案,其他看不到該函數。
靜态聲明一個函數的優點包括:
- A)兩個或兩個以上具有相同名稱的靜态函數,可用于在不同的檔案。
- B)編譯消耗減少,因為沒有外部符号處理。
讓我們做更好的了解,下面的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
注:使用靜态一定要先了解靜态便是優先記憶體配置設定,且不自動回收記憶體,函數如果調用完成不會回收函數所使用的記憶體,這裡要特别注意。
7、使用Memoization,以避免遞歸重複計算
考慮Fibonacci(斐波那契)問題;
Fibonacci問題是可以通過簡單的遞歸方法來解決:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
注:在這裡,我們考慮Fibonacci 系列從1開始,是以,該系列看起來:1,1,2,3,5,8,…
注意:從遞歸樹,我們計算fib(3)函數2次,fib(2)函數3次。這是相同函數的重複計算。如果n非常大,fib
這個簡單的技術叫做Memoization,可以被用在遞歸,加強計算速度。
fibonacci 函數Memoization的代碼,應該是下面的這個樣子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
這裡calc_fib( n )函數被main()調用。
注:這裡原作者寫的比較複雜...其實采用滾動數組,或者矩陣的話能便是更短的代碼和更好的效率。
8、避免懸空指針和野指針
一個指針的指向對象已被删除,那麼就成了懸空指針。野指針是那些未初始化的指針,需要注意的是野指針不指向任何特定的記憶體位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
當遭遇這些指針,程式通常是”怪異“的表現。
9、 永遠記住釋放你配置設定給程式的任何記憶體。上面的例子就是如果釋放dp指針(我們使用malloc()函數調用)。
原文:fortystones 譯文:oschina 注釋:驟風