程式設計修養(五) (轉)
16、把相同或近乎相同的程式碼形成和宏
—————————————————————
有人說,最好的員,就是最喜歡“偷懶”的程式,其中不無道理。
如果你有一些程式的程式碼片段很相似,或直接就是一樣的,請把他們放在一個函式中。而如果這段程式碼不多,而且會被經常使用,你還想避免函式的開銷,那麼就把他寫成宏吧。
千萬不要讓同一份程式碼或是功能相似的程式碼在多個地方存在,不然如果功能一變,你就要修改好幾處地方,這種會給維護帶來巨大的麻煩,所以,做到“一改百改”,還是要形成函式或是宏。
17、中的括號
—————————
如果一個比較複雜的表示式中,你並不是很清楚各個運算子的憂先級,即使是你很清楚優先順序,也請加上括號,不然,別人或是自己下一次讀程式時,一不小心就看走眼理解錯了,為了避免這種“誤解”,還有讓自己的程式更為清淅,還是加上括號吧。
比如,對一個結構的成員取地址:
GetUserAge( &( UserInfo->age ) );
雖然,&UserInfo->age中,->運算子的優先順序最高,但加上一個括號,會讓人一眼就看明白你的程式碼是什麼意思。
再比如,一個很長的條件判斷:
if ( ( ch[0] >= '0' || ch[0] <= '9' ) &&
( ch[1] >= 'a' || ch[1] <= 'z' ) &&
( ch[2] >= 'A' || ch[2] <= 'Z' ) )
括號,再加上空格和換行,你的程式碼是不是很容易讀懂了?
18、函式引數中的const
———————————
對於一些函式中的指標引數,如果在函式中只讀,請將其用const修飾,這樣,別人一讀到你的函式介面時,就會知道你的意圖是這個引數是[in],如果沒有const時,參數列示[in/out],注意函式介面中的const使用,利於程式的維護和避免犯一些錯誤。
雖然,const修飾的指標,如:const char* p,在C中一點用也沒有,因為不管你的宣告是不是const,指標的內容照樣能改,因為會強制轉換,但是加上這樣一個說明,有利於程式的閱讀和編譯。因為在C中,修改一個const指標所指向的時,會報一個Warning。這會引起程式設計師的注意。
C++中對const定義的就很嚴格了,所以C++中要多多的使用const,const的成員函式,const的變數,這樣會對讓你的程式碼和你的程式更加完整和易讀。(關於C++的const我就不多說了)
19、函式的引數個數(多了請用結構)
—————————————————
函式的引數個數最好不要太多,一般來說6個左右就可以了,眾多的函式引數會讓讀程式碼的人一眼看上去就很頭昏,而且也不利於維護。如果引數眾多,還請使用結構來傳遞引數。這樣做有利於資料的封裝和程式的簡潔性。
也利於使用函式的人,因為如果你的函式個數很多,比如12個,呼叫者很容易搞錯引數的順序和個數,而使用結構struct來傳遞引數,就可以不管引數的順序。
而且,函式很容易被修改,如果需要給函式增加引數,不需要更改函式介面,只需更改結構體和函式內部處理,而對於呼叫函式的程式來說,這個動作是透明的。
20、函式的返回型別,不要省略
——————————————
我看到很多程式寫函式時,在函式的返回型別方面不太注意。如果一個函式沒有返回值,也請在函式前面加上void的修飾。而有的程式設計師偷懶,在返回int的函式則什麼不修飾(因為如果不修飾,則預設返回int),這種習慣很不好,還是為了原始碼的易讀性,加上int吧。
所以函式的返回值型別,請不要省略。
另外,對於void的函式,我們往往會忘了return,由於某些C/C++的編譯器比較敏感,會報一些警告,所以即使是void的函式,我們在內部最好也要加上return的語句,這有助於程式碼的編譯。
21、goto語句的使用
—————————
N年前,開發的一代宗師——迪傑斯特拉(Dijkstra)說過:“goto statment is harmful !!”,並建議取消goto語句。因為goto語句不利於程式程式碼的維護性。
這裡我也強烈建議不要使用goto語句,除非下面的這種情況:
#define FREE(p) if(p) {
free(p);
p = NULL;
}
main()
{
char *fname=NULL, *lname=NULL, *mname=NULL;
fname = ( char* ) calloc ( 20, sizeof(char) );
if ( fname == NULL ){
goto ErrHandle;
}
lname = ( char* ) calloc ( 20, sizeof(char) );
if ( lname == NULL ){
goto ErrHandle;
}
mname = ( char* ) calloc ( 20, sizeof(char) );
if ( mname == NULL ){
goto ErrHandle;
}
......
ErrHandle:
FREE(fname);
FREE(lname);
FREE(mname);
ReportError(ERR_NO_MEMOEY);
}
也只有在這種情況下,goto語句會讓你的程式更易讀,更容易維護。(在用嵌C來對設定遊標操作時,或是對資料庫建立連結時,也會遇到這種結構)
22、宏的使用
——————
很多程式設計師不知道C中的“宏”到底是什麼意思?特別是當宏有引數的時候,經常把宏和函式混淆。我想在這裡我還是先講講“宏”,宏只是一種定義,他定義了一個語句塊,當程式編譯時,編譯器首先要一個“替換”源程式的動作,把宏引用的地方替換成宏定義的語句塊,就像文字替換一樣。這個動作術語叫“宏的展開”
使用宏是比較“危險”的,因為你不知道宏展開後會是什麼一個樣子。例如下面這個宏:
#define MAX(a, b) a>b?a:b
當我們這樣使用宏時,沒有什麼問題: MAX( num1, num2 ); 因為宏展開後變成 num1>num2?num1:num2;。 但是,如果是這樣呼叫的,MAX( 17+32, 25+21 ); 呢,編譯時出現錯誤,原因是,宏展開後變成:17+32>25+21?17+32:25+21,哇,這是什麼啊?
所以,宏在使用時,引數一定要加上括號,上述的那個例子改成如下所示就能解決問題了。
#define MAX( (a), (b) ) (a)>(b)?(a):(b)
即使是這樣,也不這個宏也還是有,因為如果我這樣呼叫 MAX(i++, j++); , 經過這個宏以後,i和j都被累加了兩次,這絕不是我們想要的。
所以,在宏的使用上還是要謹慎考慮,因為宏展開是的結果是很難讓人預料的。而且雖然,宏的執行很快(因為沒有函式呼叫的開銷),但宏會讓澎漲,使目標檔案尺寸變大,(如:一個50行的宏,程式中有1000個地方用到,宏展開後會很不得了),相反不能讓程式執行得更快(因為執行檔案變大,執行時換頁頻繁)。
因此,在決定是用函式,還是用宏時得要小心。
/Develop/read_article.?id=18272">
(版權所有,轉載時請註明出處和作者資訊)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-956445/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 程式設計師的科技道德修養 - idlewords程式設計師
- 程式設計師修煉之道~五程式設計師
- 《程式設計師自我修養》讀書筆記程式設計師筆記
- 一個野生程式設計師的自我修養程式設計師
- 程式設計師的自我修養-編譯連結程式設計師編譯
- 《程式設計師的自我修養》-讀書筆記程式設計師筆記
- 程式設計師的自我修養筆記之裝載程式設計師筆記
- 從程式設計到養生程式設計程式設計
- 很認真的談一談程式設計師的自我修養程式設計師
- 《程式設計師的自我修養》(三)——庫與執行庫程式設計師
- 《程式設計師的自我修養筆記之靜態連結》程式設計師筆記
- 養生吧,程式設計師!程式設計師
- 切圖崽的自我修養-[ES6] 程式設計風格規範程式設計
- java從零開始系列-一個前端程式設計師的自我修養Java前端程式設計師
- 遊戲設計師的自我修養(三):理解玩家遊戲設計師
- shell程式設計五程式設計
- MFC程式設計(五)C程式程式設計
- @程式設計師,再不養生就晚了程式設計師
- GitHub 熱點速覽 Vol.28:有品位程式設計師的自我修養Github程式設計師
- 《程式設計師的自我修養》筆記(二)——裝載與動態連結程式設計師筆記
- 程式設計師“求包養”攻略揭秘程式設計師
- 程式設計實驗五程式設計
- 五種Java程式設計高效程式設計方法 - BablaJava程式設計
- 程式設計師修煉之道程式設計師
- 程式設計師的職業素養(一)程式設計師
- 如何培養良好的程式設計實踐程式設計
- 如何培養良好的程式設計風格程式設計
- 接客周·程式設計養生·帶薪休假與菊部養生程式設計
- 第五講 TCP程式設計TCP程式設計
- 程式設計師修煉之道6程式設計師
- 程式設計師修煉之道7程式設計師
- 程式設計師修煉之道~三程式設計師
- 程式設計師修煉之道~四程式設計師
- 程式設計師修煉之道2程式設計師
- 程式設計師修煉之道1程式設計師
- 程式設計師修煉之道3程式設計師
- 遊戲設計師的自我修養(一):認識玩家,理解玩家遊戲設計師
- 遊戲設計師的自我修養(一):認識玩家、理解玩家遊戲設計師
- 玩轉 PHP 網路程式設計全套之多程式程式設計PHP程式設計