冒號(hào)和他的學(xué)生們
——程序員提高班紀(jì)事
18.系統(tǒng)語言
居高者形逸而神勞,處下者形勞而神逸 —《洪應(yīng)明·菜根譚》
問號(hào)忙問:“您打算比較哪些主流語言呢?”
冒號(hào)回答:“就談?wù)劦谝惶谜n提到的最流行的十二種語言吧。按語法特征可將它們分為三類:C族靜態(tài)語言五種——C、C++、Java、C#和D;非C族靜態(tài)語言兩種——VB和Delphi;動(dòng)態(tài)語言五種——Perl、PHP、Python、Ruby
和JavaScript 。”
嘆號(hào)表示懷疑:“這么多種語言怎么比較得過來?”
冒號(hào)解釋:“我們主要比較第一類的C族語言,這些也是今后學(xué)習(xí)的重點(diǎn),其他的只是泛泛而談。”
引號(hào)猜測(cè):“因?yàn)樗麄兏匾?#8221;
“可以這么說。”冒號(hào)直截了當(dāng),“毋庸諱言,在當(dāng)今的主流語言中,C族語言應(yīng)用范圍之廣、使用人數(shù)之多、影響力之巨都是其他類語言所無法比擬的。它們之間的關(guān)系從名字上就能看出:C語言的前身是B語言;其后是C++;Java曾被稱為C++++--,意思是在C++上增點(diǎn)東西再減點(diǎn)東西;C#中#就是四個(gè)疊起的加號(hào);最后D語言干脆在字母上進(jìn)行升級(jí)。”
句號(hào)推斷:“B語言、C語言、D語言,下一個(gè)該D++、D#或E語言了。”
誰知冒號(hào)卻說:“E語言已經(jīng)有了,與Java的語法很像。甚至F語言也有了,但不是C族語言,而是Fortran族的。這不,微軟還在.Net平臺(tái)上推出了F#語言,不過這里的F指的是‘Functional’,即函數(shù)式。”
逗號(hào)向往著:“不如直接搞個(gè)終極的Z語言,成為全世界程序員的唯一指定語言,多省事!”
“這難度不亞于全人類共用一種語言。”冒號(hào)笑道,“愿望是美好的,我們還得面對(duì)現(xiàn)實(shí)。不扯遠(yuǎn)了,你們先談?wù)勔幌逻@些C族語言各自的特點(diǎn)吧。”
眾人心想:老冒怎么跟國(guó)足一個(gè)毛病,老喜歡回傳,就是不直接射門,真是急煞人也!
問號(hào)揀了個(gè)軟柿子:“C語言是C族老大,又是唯一的純過程式語言,當(dāng)然與眾不同啦。”
引號(hào)一板一眼:“C++在過程式的基礎(chǔ)上又引入對(duì)象式和泛型式,同時(shí)保持了C的高效性和底層開發(fā)能力。”
逗號(hào)接道:“Java既繼承了C++的優(yōu)點(diǎn),又克服了C++的復(fù)雜性,雖然底層開發(fā)能力有所減弱,但具備平臺(tái)無關(guān)性。”
句號(hào)不緊不慢:“C#兼具C++與Java各自的優(yōu)點(diǎn),但效率上不如C++,跨平臺(tái)方面不如Java。”
嘆號(hào)后悔嘴慢:“剩下一個(gè)最陌生的D語言,在第一堂課之前還真沒聽說過,怎么擠上主流語言位置的?我想。。。呃,它總該比C++要高級(jí)吧。”
冒號(hào)評(píng)價(jià):“各位談得雖然簡(jiǎn)單了些,也算八九不離十吧。下面我稍微展開些來講。”
此時(shí)眾人有一個(gè)共同的愿望,希望老冒這次能痛快地單刀赴會(huì)、直搗黃龍。
冒號(hào)似乎看出大家的心思,開始口若懸河:“關(guān)于C語言,前面多次提到。這是一把歷久彌新的寶劍,一旦出鞘,依舊寒光逼人,鋒利無儔。有了它,便如戰(zhàn)將有了佩劍,平添一分獨(dú)闖敵營(yíng)的膽氣。盡管以現(xiàn)代的眼光來看,它存在不少缺點(diǎn),但即使拋開C語言輝煌的歷史不談,單就其以如此高齡在諸多后輩沖擊之下仍屹立不倒而論,讓人無法對(duì)其多加苛求。”
逗號(hào)提出異議:“但語言不是讓人崇拜的,而是讓人運(yùn)用的。一門語言無論過去如何榮光,如果不適應(yīng)現(xiàn)代發(fā)展趨勢(shì),還是可能被淘汰。”
“說得非常好!”冒號(hào)竟然鼓起掌來,“迄今為止本課堂對(duì)于具體知識(shí)的講授并不多,但一直提倡獨(dú)立思考,不要盲從權(quán)威。如果你們能做到這一點(diǎn),本班的目標(biāo)也就實(shí)現(xiàn)了一半。回頭再說說C語言,它源自Unix操作系統(tǒng)的開發(fā),以其良好的抽象性和可移植性取代了匯編語言作為系統(tǒng)開發(fā)語言。因其簡(jiǎn)潔實(shí)用、靈活高效,很快從系統(tǒng)領(lǐng)域發(fā)展到其他領(lǐng)域而成為通用語言。隨著新興語言的崛起以及硬件性能的大幅提高,C語言的缺點(diǎn)也日益顯著:過于寬松的類型檢查、容易出錯(cuò)的內(nèi)存管理、相對(duì)貧乏的語言特征等等。雖然自身還在發(fā)展,它的市場(chǎng)份額日益減少乃不爭(zhēng)的事實(shí)。但在相當(dāng)長(zhǎng)的時(shí)間內(nèi),它在其所擅長(zhǎng)的領(lǐng)域里仍會(huì)占舉足輕重的一席之地。如果C能借鑒C++的命名空間、重載、異常處理和STL等非OO的特征,它的生命力絕不會(huì)比任何OOP語言弱。“
引號(hào)咨詢道:“關(guān)于C語言的學(xué)習(xí),您有何建議?”
“精讀K&R的《The C Programming Language》,此書不過二百頁,堪稱C語言的劍訣。其中的R即Dennis
Ritchie,是C的創(chuàng)造者,同時(shí)也是Unix的締造者之一,是真正的大師。如今的大師,同博士、教授、院士等頭銜一樣,嚴(yán)重地通貨膨脹了。”冒號(hào)不無感慨。
問號(hào)尖銳地問:“C++既保持了C的底層開發(fā)能力,又引入了OOP,C的處境想必更加艱難吧?”
冒號(hào)坦承:“這是不假。C++成功的一個(gè)重要因素是對(duì)C語言的兼容,由此吸引了大批的C程序員。但這不是沒有代價(jià)的,C++在兼容C的同時(shí)也保留了C的許多缺陷。Java成功的地方有很多,一個(gè)不容忽視的因素是它徹底擺脫了與C兼容的桎梏。由于C++對(duì)C的改革不徹底,又過于龐雜,并且效率上不如C,這使得C仍有其生存空間。略有諷刺意味的是,對(duì)C++批判最激烈的往往來自C的社區(qū),比如Linux之父Linus Torvalds就曾激烈地批判過C++。”
“Linus?那可是我的偶像呢!”嘆號(hào)驚訝道。
冒號(hào)勸誡:“如果你因?yàn)槭撬姆劢z而后悔學(xué)C++,那就是為他人的偏執(zhí)買單,不管那人名氣有多大。”
句號(hào)指出:“C++最為人詬病的地方有:語法過于復(fù)雜,學(xué)習(xí)曲線陡、開發(fā)效率低;支持的范式過多;OOP不徹底;自省(Reflection)功能不足;支持指針操作導(dǎo)致安全隱患;沒有自動(dòng)垃圾回收,容易內(nèi)存泄漏;沒有線程支持;沒有豐富的標(biāo)準(zhǔn)庫(kù)支持圖形界面、網(wǎng)絡(luò)編程等。”
“罪狀不少哇!這些說法都有一定道理,但也有失公允。且聽我一一道來。”冒號(hào)當(dāng)起了辯護(hù)律師,“C++過于復(fù)雜這點(diǎn)沒錯(cuò),Stroustrup說過一句耐人尋味的話:一種語言不復(fù)雜是因?yàn)椴怀墒?。成人肯定比兒童?fù)雜,因?yàn)樗袚?dān)更大的責(zé)任。大家不妨看看Java從1.0到6.0的發(fā)展過程,是否應(yīng)證了這一點(diǎn)?當(dāng)然C++的復(fù)雜度的確高于其他語言,但如果不執(zhí)著于奇技淫巧,它絕非高不可攀。C++的開發(fā)效率相比Java與C#,差距主要在兩個(gè)方面:一是標(biāo)準(zhǔn)庫(kù)不夠完善,二是需要手工回收垃圾。關(guān)于前者,的確是C++的一大軟肋,標(biāo)準(zhǔn)庫(kù)竟然連企業(yè)應(yīng)用中最常用的圖形界面、網(wǎng)絡(luò)編程、數(shù)據(jù)庫(kù)處理等都不能涵蓋,嚴(yán)重障礙了生產(chǎn)力。其實(shí)C++也有苦衷,不像Java和C#那樣有大公司的鼎力支持,只靠效率極為低下的標(biāo)準(zhǔn)委員會(huì)來維護(hù)。98年的一個(gè)標(biāo)準(zhǔn)直到03年還在修訂,下一個(gè)標(biāo)準(zhǔn)至少要到09年。連Stroustrup都在哭窮,說沒有足夠的人和時(shí)間來開發(fā)標(biāo)準(zhǔn)庫(kù),可為何廣受贊譽(yù)的Boost庫(kù)至今仍徘徊在標(biāo)準(zhǔn)門外?考慮到Boost的創(chuàng)辦人大多出自標(biāo)準(zhǔn)委員會(huì),其他無此背景的類庫(kù)恐怕更難登C++之堂了。相比之下D語言更慘,雖然天生麗質(zhì),苦無豪門青睞,只好一直待字閨中。”
嘆號(hào)感慨:“金錢才是技術(shù)的最大推動(dòng)力??!”
“話糙理不糙。”冒號(hào)也很無奈,“此外,C++不支持自動(dòng)垃圾回收,是因?yàn)?/span>Stroustrup固執(zhí)地認(rèn)為這該由library來支持。一方面,C++主張RAII(Resource
Acquisition Is Initialization)原則,通過析構(gòu)函數(shù)(destructor)或智能指針(smart pointer)能在大多數(shù)情況下有效地解決內(nèi)存釋放問題;另一方面,盡管自動(dòng)垃圾回收機(jī)制逐漸為大眾接受——據(jù)說C++0x也將部分地支持它——但這種機(jī)制也存在缺陷。比如一個(gè)Java程序如果在某一時(shí)段極耗內(nèi)存,由于自動(dòng)垃圾回收的不定時(shí)性,不能保證及時(shí)清理內(nèi)存,可能會(huì)拋出OutOfMemoryError。另外,自動(dòng)垃圾回收機(jī)制并不能完全避免內(nèi)存泄漏問題,Java程序的內(nèi)存泄漏可能會(huì)比C++的更多,因?yàn)?/span>C++程序員對(duì)此更有戒心。”
問號(hào)直奔要害:“您如何看待C與C++中的指針?”
冒號(hào)欣然接招:“指針是C與C++最大的特色,其他語言要么不支持,要么支持得有限。C與C++可以說是成也指針,敗也指針。用得好可以是削鐵如泥的神兵利器,用得不好則可能是自我毀滅的罪惡淵藪。但由于二者定位于系統(tǒng)語言,而指針對(duì)于底層操作是必不可少的。同樣道理,二者的數(shù)據(jù)類型的轉(zhuǎn)換比其他靜態(tài)類型語言更自由,也是源出于此。”
句號(hào)總結(jié):“能力越大,責(zé)任越大,風(fēng)險(xiǎn)越大。”
“正是此意!”冒號(hào)重重地敲了一下桌子,“此話既適用于編程語言,也適用于程序員。至于C++缺少對(duì)自省功能的支持,也是因?yàn)樽非笮?,不愿在元?shù)據(jù)上花時(shí)間和空間。說到C++支持的范式過多,程序員過于自由,代碼不標(biāo)準(zhǔn)難維護(hù),這就如同埋怨餐館提供的菜式過多以致難以擺出一桌酒席一樣可笑。最后,指責(zé)C++不是100%OOP的說法更是荒謬之極。OOP又不是金子,含量越高越好。試圖把一切都裝進(jìn)OOP的箱子里的想法無異于削足適履。典型的如Java中的Math類,邏輯上壓根兒就不存在什么Math對(duì)象,清一色的static方法和常量就是最好的諷刺。在C++中只要在math的namespace中定義一些自由函數(shù)就可以了,自然而簡(jiǎn)潔。”
引號(hào)發(fā)覺:“您好像把對(duì)C++所有的責(zé)難都化解了。”
“可恨之人必有可憐之處嘛。”冒號(hào)俗語反用,“其實(shí)C++仍有不少亟待改進(jìn)之處,D語言就是很好的啟示。D語言的提供了可控制的垃圾回收器;支持動(dòng)態(tài)數(shù)組(dynamic
array);支持契約式設(shè)計(jì)(design by contract);廢除了C與C++ 令人頭痛的頭文件(header
file)等等。這些都是C++程序員夢(mèng)寐以求的特征。”
逗號(hào)很奇怪:“為什么D語言名氣這么???”
句號(hào)吟道:“千里馬常有,伯樂不常有,大腕伯樂更稀有。”
眾樂。
冒號(hào)結(jié)語:“C與C++同為系統(tǒng)語言,決定了它們的理念是:優(yōu)化機(jī)器的時(shí)間而不是人的時(shí)間,優(yōu)化機(jī)器的記憶而不是人的記憶;假設(shè)編譯器是愚蠢的而程序員是聰明的,因此賦予程序員更多的權(quán)利、義務(wù)與責(zé)任。無視這種背景和理念而去與其他語言相較,必不著筋節(jié)。需要強(qiáng)調(diào)的是,常見的‘C/C++’的說法很不科學(xué)。C與C++雖有千絲萬縷的聯(lián)系,但一個(gè)簡(jiǎn)單,一個(gè)復(fù)雜;一個(gè)純過程式,一個(gè)集過程式、對(duì)象式、泛型式和元編程于一體。貌合神離,不宜混為一談。”
嘆號(hào)一個(gè)問題憋了半天,不吐不快:“我有一個(gè)問題:如今電腦性能這么高,C與C++如此強(qiáng)調(diào)運(yùn)行效率還有必要嗎?”
“絕對(duì)有必要!”冒號(hào)斬釘截鐵,“其一、縱向看,用戶的耐心與電腦的速度成反比,早年一個(gè)386人們就滿足了,如今卻忍受不了586;其二、橫向比,相對(duì)緩慢的系統(tǒng)競(jìng)爭(zhēng)力也低;其三、在一些領(lǐng)域如人工智能方面,普通電腦的速度還遠(yuǎn)遠(yuǎn)不能滿足要求,超級(jí)計(jì)算機(jī)的存在就是明證;其四、仍有些程序跑在資源有限的機(jī)器上,比如嵌入式系統(tǒng)。”
引號(hào)再次要求:“能推薦一些C++方面的書嗎?”
冒號(hào)直言:“學(xué)好C一本書足矣,學(xué)好C++即使推薦十本仍有遺珠之憾??梢哉fC++是苦了編程者,甜了著書人。開個(gè)小書單:初級(jí)——《C++
Primer》和《Thinking in C++》;中級(jí)——《The C++ Programming
Language》和《Effective C++》系列;高級(jí)——《The C++ In-Depth》系列。這里還要特別推薦一下《The Design and
Evolution of C++》,從中你可以看到 C++的設(shè)計(jì)和演變的來龍去脈,極具啟發(fā)性。C++是匹無轡無鞍的野馬,看似桀驁不馴,若能順性而御,必能足踏飛燕,行千里而不勞。”