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

