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