C語言高效得簡直不合理
【譯者序:我翻譯此文并非推崇C而貶低其他語言。我翻譯此文,只是因為作者的多處精到的見解讓人深思。作者的出發點,很明顯,是純技術的;各位讀者且謹記這一點。】
多年來,我一直試圖擺脫C語言。太簡單,太多細節需要處理,太古老,太低級。我一直鐘愛Java,C++,Erlang。我用它們創建了很多項目,并且自己為這些項目感到驕傲;然而,這些語言,最終,都傷了我的心。他們做出承諾,卻無法兌現;他們專注于錯誤的東西,并且所做的“折衷”最終讓你倍感煎熬。于是,我不得不求助于C。
C就是一個萬能背包。它高效且高產,有強大的工具和廣泛的社區支持,并且它對它所做的“折衷”非常誠實。
對于其他語言,他們能讓你更快的工作,但從長遠來看,當性能和可靠性變得重要時,C將會為你省去不少麻煩事兒。我個人再次非常痛苦的學到了這一刻。
簡單直觀
C語言是非常棒的高級語言。我重復一遍,C語言是非常棒的高級語言。當然,它沒有Java、C#等高級,自然也沒有Erlang、Python或者 Javascript高級。但是,他和C++在語言的高級程度上,是一樣的;而然它比C++更加簡單。當然C++提供了更多的抽象,然而它并沒有給出比C 更高級的抽象。在使用C++時,你考慮的細節并不比你使用C時的少,除此之外,你還要考慮一堆可笑的無意義東西。
"When someone says: 'I want a programming language in which I need only say what I wish done', give him a lollipop." - Alan J. Perlis 當有人說:“我想要一種編程語言,我僅需要對它說我想干啥就行了。”那么給那個小屁孩兒一個棒棒糖吧。 Alan J. Perlis |
我們想要找一種低級語言來代替C,然而找不到;這并非是因為C語言是低級語言,相反,恰恰是因為C語言作為底層機器上的高層抽象太成功了。它如此成功,以至于讓大多數的低級語言顯得毫無意義。C就是這么擅長它所做的。
C語言的語法和語義強大而直觀。它可以用以編寫高級算法,同時也可以用以處理底層硬件邏輯。正因為其強大、簡單和直觀的語法和語義,C語言并不會給我們一些額外的認知上的負擔,從而讓編程者專注于真正重要的事情。
C顛覆了我們對低級語言的認識。這真了不起。
簡單的代碼,精致的類型
c語言是一種弱類型語言,其類型系統非常簡單。和C++還有java明顯的一個區別是,c里面你不能定義“類”(class),你不可以把所有的運行時需要的東西都放到“類”里面。你的所有工作都嚴格基于結構(struct)和聯合(union)。所有的函數調用者必須明確被調用函數的參數類型和返回值類型。所以調用者的自由相對有限。
你只是想要個香蕉,結果來了只自稱森林之王的大猩猩——Joe Armstrong
你剛剛聽起來像是c語言缺點的東西某種程度上確實一種優點:c語言的API面對用戶都力圖精簡。這避免了龐雜的框架,而力圖在簡單的類型基礎上創造一個小巧的函數庫。
而面向對象的語言往往在復雜的類型基礎上又構造了龐雜的基礎類庫,這些庫提供了大量的相互依賴的接口,他們的參數和返回值的“類”型也因此更加復雜。每一種“類”又定義了大量的復雜的方法和屬性……好吧,更加復雜了。
這并不是說吐面向對象就希望變復雜,但是他們貌似鼓勵你把事情變復雜。他們的復雜性使你很容易犯錯誤。相對來說,c就很少導致錯誤。c語言盡力構建一個簡潔、通俗的類型系統,使用它你會發現你不需要顧及那么多的依賴關系。這使你的開發變得更加簡單。
速度之王
c語言不論在處理器中還是在內存堆棧里,都是速度最快的。而且其高效不僅僅體現在速度上,即使是內存的管理以及啟動時間上,也無人望其項背。當你需要平衡空間和時間的消費時,c語言從來不會對你隱藏任何細節,原因如下:
-強大的編譯器 -k&p風格 |
每次那些更高層次的編程語言(比如java或者haskell),聲稱自己能產生接近c語言的表現從程序的時候,這在我聽來簡直就是笑話。通常,他們為了實現這一點,不得不在語法上做出一些稀奇古怪的事情,比如專門搞一些“聰明的”編譯器或者虛擬機……這種古怪的優化行為使語言失去了原本簡單的性質,更何況這種優化往往只是針對處理器
當你想要用c語言寫一些對運行速度要求嚴格的東西時,你可以很清楚的知道為什么他很快,這一點不因為你使用的編譯器或者虛擬機不同而改變。應用程序中,GC(垃圾回收)的設置將會影響運行。而人機交互將會影響垃圾回收對于數據的處理。
c語言的代碼優化直接而有效。即使你不這樣認為,在實際工作中也有大量的工具幫助你了解其中的緣故。相對來說,你根本沒有必要為此壯起膽子去嘗試學習什么虛擬機,什么“智能優化編譯器”。當你在使用cpu,內存和IO分析器的時候,c語言絕對不會讓你對底層到底發生了什么感到困惑。以上所言,不論是從處理器的角度還是從內存堆棧角度,都證明了c語言是速度之王。
更快的“編寫-運行-調試”周期
“編寫-運行-調試”這個開發周期對于程序員是十分重要的。如果這個周期足夠快,開發中的人機互動足夠多,那么你的任務就進行的足夠迅速。c具有主流靜態類型語言中最快速的人機交互性能。
樂觀是程序員的職業病,返工是他們的唯一藥方 -Kent Beck |
因為“編寫-運行-調試”周期更多的是一種開發工具的使用原則而并不是一個語言的核心,所以他經常被忽略。雖然如此,怎么宣揚這個循環對于開發速度的攻擊都不為過。悲催的是,這一循環已經被很多變成語言遺忘了,他們反而去追求使用中的代碼的可讀性。所以,事實是,c仍然是最快的語言。
調試以及核心轉儲
對于任何你想將你的代碼移植過去的系統,你幾乎都可以發現一些c語言調試工具和核心轉儲工具。他們對于你能夠快速找到源代碼中的問題所在是非常重要的。當然,他們也可能出現問題。
Error, no keyboard -- press F1 to continue. |
對于其他的編程語言來說,就沒有這么多的工具了。不論如何你都得承認,這些工具對于你c語言的變成起了十分重要的作用。假如要你寫一個c語言與其他語言的接口,或許你費了九牛二虎之力,卻做出了一個結構十分復雜,運行十分脆弱,使用根本白瞎的廢物。
如果是純粹用c寫的程序,你可以察看調用堆棧,變量,參數,當前線程……一切的內存當中最基礎的東西都毫發畢見。這真的很有效,尤其是當你面對一個已經宕機幾天的服務器進程而無計可施。而當你面對一個用其他高級語言寫就的程序是……準備受死吧……
從任何地方調用
C有一個標準化的應用程序二進制接口(ABI)支持每個操作系統,語言和平臺的存在。它不需要運行或其他固有的開銷。這意味著你編寫的代碼在C不僅是有價值的,從C代碼的調用方,但對于每一個可以想象的包,在語言和環境中還是存在。
"Portability is a result of few concepts and complete definition"
- J. Palme |
您可以使用獨立的可執行文件,腳本語言,內核代碼中,嵌入代碼的C代碼,作為一個DLL,甚至從SQL調用。這是用得上系統編程和可插拔庫。如果你想要寫的東西一旦有可用的最可能的環境和使用情況,C是唯一明智的選擇。
是的!它有瑕疵
在C語言中有許多”瑕疵“ 。它沒有邊界檢查,很容易發生內存沖突,有懸空指針和內存/資源泄漏,螺栓支持并發性,沒有模塊,沒有命名空間。錯誤處理可能相當繁瑣和冗長。當調用堆棧崩潰,或者攻擊性輸入操縱你的進程,很容易就產生一堆錯誤。
"When all else fails, read the instructions." 當其他辦法都失效時,請查看說明! - L. Lasellio |
它的瑕疵是非常非常有名的,這是一種優點。所有的語言和實現有陷阱和難題。C只是更坦率的告訴它。還有大量的靜態和運行時工具來幫你處理最常見的和危險的錯誤。世界上很多使用最廣泛和可靠的軟件是用C打造,這就是缺陷被夸大了的證據,這些瑕疵容易檢測和修復。
為了編寫couchbase,我們團隊大概花了2 + 人/月解決Erlang虛擬機的問題。我們在Erlang的編譯器上花費了大量的時間和精力,卻仍然不確定到底發生了什么,而結論是或許是我們的插件的c 語言代碼出了什么問題。我們想找出問題,然而卻找不到。最終我們確定這是Erlang的核心里面有一個條件矛盾錯誤。這是我們唯一的成果。而太多的語言抽象掉了太多的東西,這無疑增加了類似我們遇到的困難。
最初,出于性能原因,我們決定用c重寫couchbase的代碼,并且決定couchbase的幾個新的特性也用c來寫。令人驚異的是,顯然事實證明,c 語言提供了對于程序的良好控制能力,而我們因此更容易快速找出程序的問題并進行調試。長遠來看,c語言顯然具有良好的生產效率。
我總是告誡自己,我需要一個更加高效的可以替代c語言的東西。它只要可以修正程序里面那寫毛糙的細節然后解決問題就可以了。但是從事實來看,不論是從語法、從語義、從工具或者從“自頂至底”的開發方法來看,沒有什么可以值得我們為止付出努力。到現在為止,c語言毫無疑問的是最高效的語言,我認為短期內這不會有任何改變。
你可以在twitter上“推”我一下,然后就可以了解我對編程的一些看法以及couchbase的開發進度了~
原文鏈接:http://www.oschina.net/translate/the_unreasonable_effectiveness_of_c