1.引言
還記得當年學數學、英語都有個竅門,那就是搞個錯題集。經常復習一下這個錯題集,就可以避免下次犯同樣的錯誤。而幾乎所有的程序員都是從犯錯誤開始的,我們也很有必要總結一下編程新手的常見錯誤,本文的目的在于此。文中所列出的都是筆者在項目開發(fā)中接觸到的新手真實的言談,筆者學學*腔調,姑且稱之為“錯誤語錄”。
2.語錄
(1)“我的程序都是對的,可結果不對”
想想你的周圍,是不是也有人說這樣的話?如果你也曾經說過,那就此打住,不要再說這句話,因為這句話只會顯示說話者的無知。既然程序都是對的,那為什么結果不對?
(2)“程序=算法+數據結構”
如果剛剛學完C語言,我們說這樣的話,完全可以理解,而且可以說是正確的。但是如果你是一位即將從事C/C++編程的程序員,那么很遺憾,這個說法只能判錯,殊不知,世界上還有另一種說法:
程序 = 對象 + 消息
“程序=算法+數據結構”只對面向過程的語言(C)成立,而對面向對象的語言(C++),則只能表述為“程序=對象+消息”。傳統(tǒng)的過程式編程語言以過程為中心以算法為驅動,面向對象的編程語言則以對象為中心以消息為驅動。這里的消息是廣義的,對象A調用了對象B的成員函數,可看作對象A給B發(fā)消息。
(3)“程序編出來,運行正確就行了”
運行正確的程序并不一定是好程序,程序員時刻要牢記的一條就是自己寫的程序不僅是給自己看的,要讓別人也能輕易地看懂。很遺憾,許多的編程新手不能清晰地駕馭軟件的結構,對頭文件和實現文件的概念含糊不清,寫出來的程序可讀性很差。
C程序采用模塊化的編程思想,需合理地將一個很大的軟件劃分為一系列功能獨立的部分合作完成系統(tǒng)的需求,在模塊的劃分上主要依據功能。模塊由頭文件和實現文件組成,對頭文件和實現文件的正確使用方法是:
規(guī)則1 頭文件(.h)中是對于該模塊接口的聲明,接口包括該模塊提供給其它模塊調用的外部函數及外部全局變量,對這些變量和函數都需在.h中文件中冠以extern關鍵字聲明;
規(guī)則2 模塊內的函數和全局變量需在.c文件開頭冠以static關鍵字聲明;
規(guī)則3 永遠不要在.h文件中定義變量;
許多程序員對定義變量和聲明變量混淆不清,定義變量和聲明變量的區(qū)別在于定義會產生內存分配的操作,是匯編階段的概念;而聲明則只是告訴包含該聲明的模塊在連接階段從其它模塊尋找外部函數和變量。如:
/*模塊1頭文件:module1.h*/
int a = 5; /* 在模塊1的.h文件中定義int a */
/*模塊1實現文件:module1 .c*/
#include “module1.h” /* 在模塊1中包含模塊1的.h文件 */
/*模塊2實現文件: module2.c*/
#include “module1.h” /* 在模塊2中包含模塊1的.h文件 */
/*模塊2 實現文件:module3 .c*/
#include “module1.h” /* 在模塊3中包含模塊1的.h文件 */
以上程序的結果是在模塊1、2、3中都定義了整型變量a,a在不同的模塊中對應不同的地址單元,這明顯不符合編寫者的本意。正確的做法是:
/*模塊1頭文件:module1.h*/
extern int a; /* 在模塊1的.h文件中聲明int a */
/*模塊1實現文件:module1 .c*/
#include “module1.h” /* 在模塊1中包含模塊1的.h文件 */
int a = 5; /* 在模塊1的.c文件中定義int a */
/*模塊2 實現文件: module2 .c*/
#include “module1.h” /* 在模塊2中包含模塊1的.h文件 */
/*模塊3 實現文件: module3 .c*/
#include “module1.h” /* 在模塊3中包含模塊1的.h文件 */
這樣如果模塊1、2、3操作a的話,對應的是同一片內存單元。
規(guī)則4 如果要用其它模塊定義的變量和函數,直接包含其頭文件即可。
許多程序員喜歡這樣做,當他們要訪問其它模塊定義的變量時,他們在本模塊文件開頭添加這樣的語句:
extern int externVar;
拋棄這種做法吧,只要頭文件按規(guī)則1完成,某模塊要訪問其它模塊中定義的全局變量時,只要包含該模塊的頭文件即可。
還記得當年學數學、英語都有個竅門,那就是搞個錯題集。經常復習一下這個錯題集,就可以避免下次犯同樣的錯誤。而幾乎所有的程序員都是從犯錯誤開始的,我們也很有必要總結一下編程新手的常見錯誤,本文的目的在于此。文中所列出的都是筆者在項目開發(fā)中接觸到的新手真實的言談,筆者學學*腔調,姑且稱之為“錯誤語錄”。
2.語錄
(1)“我的程序都是對的,可結果不對”
想想你的周圍,是不是也有人說這樣的話?如果你也曾經說過,那就此打住,不要再說這句話,因為這句話只會顯示說話者的無知。既然程序都是對的,那為什么結果不對?
(2)“程序=算法+數據結構”
如果剛剛學完C語言,我們說這樣的話,完全可以理解,而且可以說是正確的。但是如果你是一位即將從事C/C++編程的程序員,那么很遺憾,這個說法只能判錯,殊不知,世界上還有另一種說法:
程序 = 對象 + 消息
“程序=算法+數據結構”只對面向過程的語言(C)成立,而對面向對象的語言(C++),則只能表述為“程序=對象+消息”。傳統(tǒng)的過程式編程語言以過程為中心以算法為驅動,面向對象的編程語言則以對象為中心以消息為驅動。這里的消息是廣義的,對象A調用了對象B的成員函數,可看作對象A給B發(fā)消息。
(3)“程序編出來,運行正確就行了”
運行正確的程序并不一定是好程序,程序員時刻要牢記的一條就是自己寫的程序不僅是給自己看的,要讓別人也能輕易地看懂。很遺憾,許多的編程新手不能清晰地駕馭軟件的結構,對頭文件和實現文件的概念含糊不清,寫出來的程序可讀性很差。
C程序采用模塊化的編程思想,需合理地將一個很大的軟件劃分為一系列功能獨立的部分合作完成系統(tǒng)的需求,在模塊的劃分上主要依據功能。模塊由頭文件和實現文件組成,對頭文件和實現文件的正確使用方法是:
規(guī)則1 頭文件(.h)中是對于該模塊接口的聲明,接口包括該模塊提供給其它模塊調用的外部函數及外部全局變量,對這些變量和函數都需在.h中文件中冠以extern關鍵字聲明;
規(guī)則2 模塊內的函數和全局變量需在.c文件開頭冠以static關鍵字聲明;
規(guī)則3 永遠不要在.h文件中定義變量;
許多程序員對定義變量和聲明變量混淆不清,定義變量和聲明變量的區(qū)別在于定義會產生內存分配的操作,是匯編階段的概念;而聲明則只是告訴包含該聲明的模塊在連接階段從其它模塊尋找外部函數和變量。如:
/*模塊1頭文件:module1.h*/
int a = 5; /* 在模塊1的.h文件中定義int a */
/*模塊1實現文件:module1 .c*/
#include “module1.h” /* 在模塊1中包含模塊1的.h文件 */
/*模塊2實現文件: module2.c*/
#include “module1.h” /* 在模塊2中包含模塊1的.h文件 */
/*模塊2 實現文件:module3 .c*/
#include “module1.h” /* 在模塊3中包含模塊1的.h文件 */
以上程序的結果是在模塊1、2、3中都定義了整型變量a,a在不同的模塊中對應不同的地址單元,這明顯不符合編寫者的本意。正確的做法是:
/*模塊1頭文件:module1.h*/
extern int a; /* 在模塊1的.h文件中聲明int a */
/*模塊1實現文件:module1 .c*/
#include “module1.h” /* 在模塊1中包含模塊1的.h文件 */
int a = 5; /* 在模塊1的.c文件中定義int a */
/*模塊2 實現文件: module2 .c*/
#include “module1.h” /* 在模塊2中包含模塊1的.h文件 */
/*模塊3 實現文件: module3 .c*/
#include “module1.h” /* 在模塊3中包含模塊1的.h文件 */
這樣如果模塊1、2、3操作a的話,對應的是同一片內存單元。
規(guī)則4 如果要用其它模塊定義的變量和函數,直接包含其頭文件即可。
許多程序員喜歡這樣做,當他們要訪問其它模塊定義的變量時,他們在本模塊文件開頭添加這樣的語句:
extern int externVar;
拋棄這種做法吧,只要頭文件按規(guī)則1完成,某模塊要訪問其它模塊中定義的全局變量時,只要包含該模塊的頭文件即可。

