程式設計修養(七) (轉)
28、||和&&的語句順序
————————————
條件語句中的這兩個“與”和“或”運算子一定要小心,它們的表現可能和你想像的不一樣,這裡條件語句中的有些行為需要和說一下:
express1 || express2
先執行express1如果為“真”,express2將不被執行,express2僅在express1為“假”時才被執行。因為第一個表示式為真了,整個表示式都為真,所以沒有必要再去執行第二個表示式了。
express1 && express2
先執行表示式express1如果為“假”,express2將不被執行,express2僅在express1為“真”時才被執行。因為第一個表示式為假了,整個表示式都為假了,所以沒有必要再去執行第二個表示式了。
於是,他並不是你所想像的所有的表示式都會去執行,這點一定要明白,不然你的會出現一些莫明的執行時錯誤。
例如,下面的程式:
if ( sum > 100 &&
( ( fp=fopen( filename,"a" ) ) != NULL ) {
fprintf(fp, "Warring: it beyond one hundred
");
......
}
fprintf( fp, " sum is %id
", sum );
fclose( fp );
本來的意圖是,如果sum > 100 ,向中寫一條出錯資訊,為了方便,把兩個條件判斷寫在一起,於是,如果sum<=100時,開啟檔案的操作將不會做,最後,fprintf和fclose就會發現未知的結果。
再比如,如果我想判斷一個字元是不是有內容,我得判斷這個字串指標是不為空(NULL)並且其內容不能為空(Empty),一個是空指標,一個是空內容。我也許會這樣寫:
if ( ( p != NULL ) && ( strlen(p) != 0 ))
於是,如果p為NULL,那麼strlen(p)就不會被執行,於是,strlen也就不會因為一個空指標而“操作”或是一個“Core Dump”了。
記住一點,條件語句中,並非所有的語句都會執行,當你的條件語句非常多時,這點要尤其注意。
29、儘量用for而不是while做迴圈
———————————————
基本上來說,for可以完成while的功能,我是建議儘量使用for語句,而不要使用while語句,特別是當迴圈體很大時,for的優點一下就體現出來了。
因為在for中,迴圈的初始、結束條件、迴圈的推進,都在一起,一眼看上去就知道這是一個什麼樣的迴圈。剛出學校的程式一般對於連結喜歡這樣來:
p = pHead;
while ( p ){
...
...
p = p->next;
}
當while的語句塊變大後,你的程式將很難讀,用for就好得多:
for ( p=pHead; p; p=p->next ){
..
}
一眼就知道這個迴圈的開始條件,結束條件,和迴圈的推進。大約就能明白這個迴圈要做個什麼事?而且,程式維護進來很容易,不必像while一樣,在一個編輯器中上上下下的搗騰。
30、請sizeof型別而不是變數
—————————————
許多程式設計師在使用sizeof中,喜歡sizeof變數名,例如:
int re[100];
char filename[20];
struct UserInfo usr[100];
在sizeof這三個的變數名時,都會返回正確的結果,於是許多程式設計師就開始sizeof變數名。這個習慣很雖然沒有什麼不好,但我還是建議sizeof型別。
我看到過這個的程式:
pScore = (int*) malloc( SUBJECT_CNT );
memset( pScore, 0, sizeof(pScore) );
...
此時,sizeof(pScore)返回的就是4(指標的長度),不會是整個陣列,於是,memset就不能對這塊進行初始化。為了程式的易讀和易維護,我強烈建議使用型別而不是變數,如:
對於score: sizeof(int) * 100 /* 100個int */
對於filename: sizeof(char) * 20 /* 20個char */
對於usr: sizeof(struct UserInfo) * 100 /* 100個UserInfo */
這樣的程式碼是不是很易讀?一眼看上去就知道什麼意思了。
另外一點,sizeof一般用於分配記憶體,這個特性特別在多維陣列時,就能體現出其優點了。如,給一個字串陣列分配記憶體,
/*
* 分配一個有20個字串,
* 每個字串長100的記憶體
*/
char* *p;
/*
* 錯誤的分配方法
*/
p = (char**)calloc( 20*100, sizeof(char) );
/*
* 正確的分配方法
*/
p = (char**) calloc ( 20, sizeof(char*) );
for ( i=0; i<20; i++){
/*p = (char*) calloc ( 100, sizeof(char) );*/
p[i] = (char*) calloc ( 100, sizeof(char) );
}
(注:上述語句被註釋掉的是原來的,是錯誤的,由dasherest朋友指正,謝謝)
為了程式碼的易讀,省去了一些判斷,請注意這兩種分配的方法,有本質上的差別。
31、不要忽略Warning
——————————
對於一些編譯時的警告資訊,請不要忽視它們。雖然,這些Warning不會妨礙目的碼的生成,但這並不意味著你的程式就是好的。必竟,並不是編譯成功的程式才是正確的,編譯成功只是萬里長征的第一步,後面還有大風大浪在等著你。從編譯程式開始,不但要改正每個error,還要修正每個warning。這是一個有修養的程式設計師該做的事。
一般來說,一面的一些警告資訊是常見的:
1)宣告瞭未使用的變數。(雖然不會編譯這種變數,但還是把它從源程式中註釋或是刪除吧)
2)使用了隱晦宣告的。(也許這個函式在別的C檔案中,編譯時會出現這種警告,你應該這使用之前使用extern關鍵字宣告這個函式)
3)沒有轉換一個指標。(例如malloc返回的指標是void的,你沒有把之轉成你實際型別而報警,還是手動的在之前明顯的轉換一下吧)
4)型別向下轉換。(例如:float f = 2.0; 這種語句是會報警告的,編譯會告訴你正試圖把一個double轉成float,你正在閹割一個變數,你真的要這樣做嗎?還是在2.0後面加個f吧,不然,2.0就是一個double,而不是float了)
不管怎麼說,編譯器的Warning不要小視,最好不要忽略,一個程式都做得出來,何況幾個小小的Warning呢?
32、書寫De版和Release版的程式
————————————————
程式在開發過程中必然有許多程式設計師加的資訊。我見過許多專案組,當程式開發結束時,發動群眾刪除程式中的除錯資訊,何必呢?為什麼不像VC++那樣建立兩個版本的目的碼?一個是debug版本的,一個是Release版的。那些除錯資訊是那麼的寶貴,在日後的維護過程中也是很寶貴的東西,怎麼能說刪除就刪除呢?
利用預編譯技術吧,如下所示宣告除錯函式:
#ifdef DEBUG
void TRACE(char* fmt, ...)
{
......
}
#else
#define TRACE(char* fmt, ...)
#endif
於是,讓所有的程式都用TRACE輸出除錯資訊,只需要在在編譯時加上一個引數“-DDEBUG”,如:
cc -DDEBUG -o target target.c
於是,預編譯器發現DEBUG變數被定義了,就會使用TRACE函式。而如果要釋出給了,那麼只需要把取消“-DDEBUG”的引數,於是所有用到TRACE宏,這個宏什麼都沒有,所以源程式中的所有TRACE語言全部被替換成了空。一舉兩得,一箭雙鵰,何樂而不為呢?
順便提一下,兩個很有用的宏,一個是“__FILE__”,一個是“__LINE__”,分別表示,所在的原始檔和行號,當你除錯資訊或是輸出錯誤時,可以使用這兩個宏,讓你一眼就能看出你的錯誤,出現在哪個檔案的第幾行中。這對於用C/C++做的大工程非常的管用。
綜上所述32條,都是為了三大目的——
1、程式程式碼的易讀性。
2、程式程式碼的可維護性,
3、程式程式碼的穩定可靠性。
有修養的程式設計師,就應該要學會寫出這樣的程式碼!這是任何一個想做高手所必需面對的細小的問題,程式設計高手不僅技術要強,基礎要好,而且最重要的是要有“修養”!
好的產品絕不僅僅是技術,而更多的是整個軟體的易維護和可靠性。
軟體的維護有大量的工作量花在程式碼的維護上,軟體的Upgrade,也有大量的工作花在程式碼的組織上,所以好的程式碼,清淅的,易讀的程式碼,將給大大減少軟體的維護和升級成本。
/Develop/read_article.?id=18274">
(版權所有,轉載時請註明出處和作者資訊)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-956448/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 程式設計修養(一) (轉)程式設計
- 程式設計修養(二) (轉)程式設計
- 程式設計修養(三) (轉)程式設計
- 程式設計修養(五) (轉)程式設計
- 程式設計修養(六) (轉)程式設計
- 程式設計修養(四) (轉)程式設計
- 程式設計師的自我修養程式設計師
- 程式設計師修煉之道—程式設計師如何提高自我修養(2)程式設計師
- 程式設計師修煉之道——程式設計師如何提高自我修養(1)程式設計師
- iOS 程式設計師的自我修養 — 讀《程式設計師的自我修養 連結、裝載與庫》iOS程式設計師
- 程式設計師如何提高自我修養(4)程式設計師
- 程式設計師的自我修養之全棧程式設計師程式設計師全棧
- 程式設計師自我修養之程式設計經驗總結程式設計師
- 七、GO 程式設計模式: 修飾器Go程式設計設計模式
- 一個野生程式設計師的自我修養程式設計師
- 程式設計師的科技道德修養 - idlewords程式設計師
- 淺談程式設計師的數學修養程式設計師
- 《程式設計師自我修養》讀書筆記程式設計師筆記
- 《程式設計師的自我修養》-讀書筆記程式設計師筆記
- 程式設計師的自我修養-編譯連結程式設計師編譯
- 讀書筆記 - 《程式設計師的自我修養》筆記程式設計師
- 《程式設計師的自我修養》讀書總結程式設計師
- 程式設計師的自我修養:溫故而知新程式設計師
- 程式設計師的自我修養筆記之裝載程式設計師筆記
- 【程式設計師的自我修養①】iOS記憶體管理程式設計師iOS記憶體
- 給每個菜鳥程式設計師的修養之道程式設計師
- 產品經理看程式設計師的自我修養程式設計師
- 高效程式設計師應該養成的七個習慣程式設計師
- 《程式設計師的自我修養》(三)——庫與執行庫程式設計師
- 很認真的談一談程式設計師的自我修養程式設計師
- 很認真地聊一聊程式設計師的自我修養程式設計師
- 很認真的聊一聊程式設計師的自我修養程式設計師
- 從程式設計到養生程式設計程式設計
- 轉贈《程式設計師的職業素養》程式設計師
- 《程式設計師的自我修養筆記之靜態連結》程式設計師筆記
- 程式設計師自我修養之實現自我的10大方法程式設計師
- 編寫簡練程式碼是程式設計師的職業修養之本程式設計師
- 【免費直播】七月大神乾貨速遞:程式設計師的自我修養&高效學習方法程式設計師