C語言已死?原文及“駁”、“駁‘駁’”

來源:互聯網
上載者:User
近日,一篇《C語言已經死了,5個需要忘卻它的理由》引發了一場空前熱烈的討論,“駁”及“駁‘駁’”相繼出現。以下是三篇文章的原文:

C語言已經死了,5個需要忘卻它的理由

 

  現在,有很多C/C++程式員總是自命不凡,看不起其他開發人員。其實,或許別人更看不起他呢!

  學生時代,我也曾醉心於C/C++,但時至今日,始終無法寫出無懈可擊的C++代碼,所以我始終認為我不會C/C++。這些年,我一直在尋找編寫C++代碼的最佳模式。但是,老實說,我還沒有見到過哪個稱得上高手的C++程式員,也沒有見到過寫得Very good的C/C++代碼。C/C++代碼總是醜陋不堪,BUG叢生!

  我用C語言編程已經超過20年了。我寫過C語言的編譯器、C語言的調試器、用C開發的其他語言、遊戲、用戶端程式和伺服器程式,你說吧!還有什麼是我沒寫過的。還有我的書架上充斥著折了角的K&R和Steele的書。我太瞭解C語言了,但是,我討厭他。十分討厭!

  當我讀到一篇部落格,題目是“為什麼每個程式員都應該學習C語言?”時,我真是雞皮疙瘩滿地。如果你真的是個專業的程式員的話,你肯定覺得這是個天大的笑話,儘管作者的本意也許不是這樣的。這篇反駁的文章有點意思,但是還是沒有抓住本質。所以我展開了說一下。有以下5個原因來說明,為什麼那些會C語言,並且使用C語言的程式員,現在不但應該去用別的語言,而且應該忘記他們學習C語言過程中的那些煩人的東西。

  1、記憶體配置

  僅僅關於這一點我就能寫整整一篇文章了,也許能寫一本書,甚至還有可能寫出能夠塞滿圖書館技術書籍那塊,那麼多的內容。記憶體配置和儲存單元分配的存在確確實實是個大麻煩。你要不就是分配太少的記憶體不夠用,要不就是分配了太多記憶體浪費掉。這裡的問題就是:怎麼把它初始化為零呢?還是乾脆就不初始化它。但最撓頭的步驟還是釋放記憶體。所有已有的工具包都會協助你確認,你是否已經釋放了之前分配的每一位的記憶體,在釋放完之後是否永遠不使用它,並且會阻止你,永遠不要釋放它第兩次。更嚴重的是,分配記憶體和釋放記憶體在C語言中都是很慢的,非常慢。使用記憶體配置時,要考慮的各種特殊情況,我真是連想都不願意去想,只要問題(對象)的大小合適,我更願意使用棧空間或者事先分配的結構空間。如果這麼做的話,我就有更值得煩惱的事了。話說回來,發明垃圾處理器那人真應該得諾貝爾獎。

  2、多線程

  我過去是喜歡C語言的,真的。直到我開始用C開發並維護多線程的伺服器。在為串連相衝突的線程保護資料方面,C語言沒有為程式員提供那怕一點點的協助。你在使用單線程的日子裡獲得的每一個直覺、經驗,用在多線程的時候都是錯誤的。至少JAVA有表示同步的關鍵字和備有證明檔案(但是是個很奇怪的檔案)的記憶體,但即使是這樣,除非你使用新的javax.concurrent,否則也只能在那些巨大的平行擺放的機器們面前崩潰。回到C語言上:在類比生產的環境下,堅持一個星期在資料中心調試一個死結(這事真的發生過)。而JAVA卻只需要Ctrl+Break!天哪!!!

  3、指標

  指標太難以控制了,太陰險了;我甚至沒有委婉一點的方式去形容它。我生命中每年都有幾個月被用來調試那些奇怪的指標問題。我過去常常努力擷取所有的訣竅,比方說難以理解的構成符、聯合體和位移量,以及重用最後兩位做標記,還有所有其他的訣竅。但我發現這麼做根本不值得。其他語言的靜態引用就可以解決了。

  4、過早的最佳化

  說到訣竅,你是否曾經浪費腦細胞去研究究竟*p++是不是比p[i]快?你是否曾經花時間去試著做點變化來代替乘法,或者去嘗試使迴圈中的倒置運行更快的方法?還在為傳遞一個參數的速度和反對添加結構,並且傳遞它的速度一樣而苦惱不已?停吧!演算法是速度的關鍵,程式員的水平決定了他會使用那些演算法。知道這一點能讓你的程式更好,更快一點並且讓你的腦袋少扭幾個筋。好吧,有一些例子也許可以這樣做的……不,你就別那麼做就行了!

  5、測試

  你最喜歡的C的單元測試的工具是哪個?嗯…一個也想不到?單元測試一定是一點也不重要,是吧?或者是太麻煩了,很難跟上進度,浪費時間。你可以把這個時間用到更加有用的事情上,讓它只佔用工作時間的1%,那還比較合適。或者在資料中心,通過最佳化的沒有標記的圖形來調試這個僅僅由100個同時線上使用者引起的問題。

  我本來應該繼續再說一些原因的,但是5個現在就足夠了;說完這些,現在感覺好點了。C以前是非常棒的…那是在1984年的時候。直到今天,那些用C寫的新代碼都讓我感到驚喜…如果你讓我比較的話,我覺得C++只是比C稍微好點。如果你想要學些老一點的語言,不妨嘗試Forth,Lis,或者APL。這些老式的語言起碼能教會你,用不同的而且優雅的方式去思考你的程式。

淺薄與偏見 駁“C語言已經死了”

 

  現在,有很多C/C++程式員總是自命不凡,看不起其他開發人員。其實,或許別人更看不起他呢!

  >> 有偏見的永遠只是個體,而不是群體。作者加了後面那句,無疑證明有偏見的不是C/C++程式員,而正是他自己。

  學生時代,我也曾醉心於C/C++,但時至今日,始終無法寫出無懈可擊的C++代碼,所以我始終認為我不會C/C++。這些年,我一直在尋找編寫C++代碼的最佳模式。但是,老實說,我還沒有見到過哪個稱得上高手的C++程式員,也沒有見到過寫得Very good的C/C++代碼。C/C++代碼總是醜陋不堪,BUG叢生!

  >> 這段話更加荒謬了。沒見過優秀的C/C++代碼? C++標準庫(STL)如此優雅。況且,有那麼多經典的C/C++開源作品,以及無意之中泄漏的Windows NT核心源碼,哪一樣不是絕世之作?我為作者淺陋感到難過。

  我用C語言編程已經超過20年了。我寫過C語言的編譯器、C語言的調試器、用C開發的其他語言、遊戲、用戶端程式和伺服器程式,你說吧!還有什麼是我沒寫過的。還有我的書架上充斥著折了角的K&R和Steele的書。我太瞭解C語言了,但是,我討厭他。十分討厭!

  當我讀到一篇部落格,題目是"為什麼每個程式員都應該學習C語言?"時,我真是雞皮疙瘩滿地。如果你真的是個專業的程式員的話,你肯定覺得這是個天大的笑話,儘管作者的本意也許不是這樣的。這篇反駁的文章有點意思,但是還是沒有抓住本質。所以我展開了說一下。有以下5個原因來說明,為什麼那些會C語言,並且使用C語言的程式員,現在不但應該去用別的語言,而且應該忘記他們學習C語言過程中的那些煩人的東西。

  1、記憶體配置

  僅僅關於這一點我就能寫整整一篇文章了,也許能寫一本書,甚至還有可能寫出能夠塞滿圖書館技術書籍那塊,那麼多的內容。記憶體配置和儲存單元分配的存在確確實實是個大麻煩。你要不就是分配太少的記憶體不夠用,要不就是分配了太多記憶體浪費掉。這裡的問題就是:怎麼把它初始化為零呢?還是乾脆就不初始化它。但最撓頭的步驟還是釋放記憶體。所有已有的工具包都會協助你確認,你是否已經釋放了之前分配的每一位的記憶體,在釋放完之後是否永遠不使用它,並且會阻止你,永遠不要釋放它第兩次。更嚴重的是,分配記憶體和釋放記憶體在C語言中都是很慢的,非常慢。使用記憶體配置時,要考慮的各種特殊情況,我真是連想都不願意去想,只要問題(對象)的大小合適,我更願意使用棧空間或者事先分配的結構空間。如果這麼做的話,我就有更值得煩惱的事了。話說回來,發明垃圾處理器那人真應該得諾貝爾獎。

  >> 記憶體管理是程式設計中最經典的話題。GC無疑是記憶體管理一個偉大的變革,但是我只是把它看作記憶體管理的一個解決方案,而認為不是唯一的解決方案。比GC更加優雅的方案不見得沒有。我比較傾向於在特定的情況下選擇合適的記憶體管理方案,而不是沒有任何選擇的餘地,而這正是C/C++的偉大之處。 所有那些GC語言(如Java、C#等)均把這個解決方案強加給程式員,這一定程度上來說減輕了程式員的負擔,但是也同時約束了程式員的主觀能動性。"分配記憶體和釋放記憶體在C語言中都是很慢的"?不知道作者從哪裡獲得的結論。

  2、多線程

  我過去是喜歡C語言的,真的。直到我開始用C開發並維護多線程的伺服器。在為串連相衝突的線程保護資料方面,C語言沒有為程式員提供那怕一點點的協助。你在使用單線程的日子裡獲得的每一個直覺、經驗,用在多線程的時候都是錯誤的。至少JAVA有表示同步的關鍵字和備有證明檔案(但是是個很奇怪的檔案)的記憶體,但即使是這樣,除非你使用新的javax.concurrent,否則也只能在那些巨大的平行擺放的機器們面前崩潰。回到C語言上:在類比生產的環境下,堅持一個星期在資料中心調試一個死結(這事真的發生過)。而JAVA卻只需要Ctrl+Break!天哪!!!

  >> C/C++語言本身確實沒有太多MultiThead的支援,這種情況在C++0x出來後可望改變。但是,請記住C/C++永遠傾向於你使用成熟的庫來解決問題。

  3、指標

  指標太難以控制了,太陰險了;我甚至沒有委婉一點的方式去形容它。我生命中每年都有幾個月被用來調試那些奇怪的指標問題。我過去常常努力擷取所有的訣竅,比方說難以理解的構成符、聯合體和位移量,以及重用最後兩位做標記,還有所有其他的訣竅。但我發現這麼做根本不值得。其他語言的靜態引用就可以解決了。

  >> 指標是C/C++過於靈活的體現。使用指標的代碼可以寫得很醜陋,但一樣可以很優雅。——這一點上用何種語言不會有區別。我相信,可以寫出優雅的Java代碼,那麼也一定可以寫出同樣優雅的C/C++代碼。而反之則未必(因為有些C++某些範式是Java所不能支援的)。C/C++語言中的選擇太多,這的確是令人困惑的,但不見得是劣勢。我對C/C++程式員的建議是,多瞭解和使用C++標準庫,而不是過於糾纏指標相關的細節。

  4、過早的最佳化

  說到訣竅,你是否曾經浪費腦細胞去研究究竟*p++是不是比p[i]快?你是否曾經花時間去試著做點變化來代替乘法,或者去嘗試使迴圈中的倒置運行更快的方法?還在為傳遞一個參數的速度和反對添加結構,並且傳遞它的速度一樣而苦惱不已?停吧!演算法是速度的關鍵,程式員的水平決定了他會使用那些演算法。知道這一點能讓你的程式更好,更快一點並且讓你的腦袋少扭幾個筋。好吧,有一些例子也許可以這樣做的……不,你就別那麼做就行了!

  >> 演算法最佳化是程式設計的關鍵。但是通常情況下,所有語言(包括C/C++)的程式員研究的是關鍵路徑的最佳化。研究*p++是不是比p[i]快?我相信這是標準庫的實現者要考慮的事情。所不同的是,C/C++程式員也可以和標準庫的作者一樣去考慮這些細節,而其他語言的程式員被剝奪了這個權利。

  說到最佳化,話題就多了。我曾經向C#的Dictionary中插入了1億條整數(從1萬多個文字檔中讀入),結果發現程式運行了整整一個下午仍然沒有完成。而我改用C++的std::map,20分鐘就搞定了。再試試對50萬條自訂的結構體資料進行排序,我相信你和我一樣,會深深喜歡上C++的的高效而優雅。

  5、測試

  你最喜歡的C的單元測試的工具是哪個?嗯…一個也想不到?單元測試一定是一點也不重要,是吧?或者是太麻煩了,很難跟上進度,浪費時間。你可以把這個時間用到更加有用的事情上,讓它只佔用工作時間的1%,那還比較合適。或者在資料中心,通過最佳化的沒有標記的圖形來調試這個僅僅由100個同時線上使用者引起的問題。

  >> C++的測試載入器,作者居然一個都想不到,我只能猜想可能他是比較喜歡自己製造輪子的那一類。和JUnit對應的CppUnit,難道也想不到?提起CppUnit,我以前用它進行單元測試,但從實現架構上說,我認為它繼承了Java代碼的臃腫。我在WINX中提供了一個Mini版本的CppUnit,代碼量大概只有幾百行,功能絕不比CppUnit弱。(要瞭解WINX,請看這裡)。

  我本來應該繼續再說一些原因的,但是5個現在就足夠了;說完這些,現在感覺好點了。C以前是非常棒的…那是在1984年的時候。直到今天,那些用C寫的新代碼都讓我感到驚喜…如果你讓我比較的話,我覺得C++只是比C稍微好點。如果你想要學些老一點的語言,不妨嘗試Forth,List,或者APL。這些老式的語言起碼能教會你,用不同的而且優雅的方式去思考你的程式。

  >> 新生的語言,必然會在吸收舊的語言上基礎上進行改進。看一個語言的生命力,並不在於看它某些地方存在的不足。事物會發展,並趨於完善。相信C++0x出來後,C/C++語言又將獲得新的生命力。單看Java、C#等幾個新一代的語言,其中有如此多的C++烙印,就證明了C/C++的影響是巨大的。動不動說一門語言死了,是一種淺薄。

 並非偏見 也駁“駁'C語言已經死了'”

 

  >> 有偏見的永遠只是個體,而不是群體。作者加了後面那句,無疑證明有偏見的不是C/C++程式員,而正是他自己。

  錯了,真理是站在少數人這邊的,當一種變革將發生的時候,帶有偏見往往是福士是傳統力量。

  >> 這段話更加荒謬了。沒見過優秀的C/C++代碼? C++標準庫(STL)如此優雅。況且,有那麼多經典的C/C++開源作品,以及無意之中泄漏的Windows NT核心源碼,哪一樣不是絕世之作?我為作者淺陋感到難過。

  STL的代碼並不優雅,缺乏functional programming機制支援的C++對於實現algorithm非常的牽強,比方我要find(v.begin(), v.end(), compare);的時候(v是一個自訂的結構),我必須在函數外面寫一個比較函數,如果要帶一些內容相關的話還得寫一個functor類,非常的醜陋不堪,實用性大打折扣。而FP系的語言來說,可以非常自然的寫一個匿名函數。STL裡所標榜的容器,演算法等概念,在FP裡早就原生支援了,而且要優雅的多。至於NT代碼這個我沒看過不好說,但是據說代碼裡有不少當初程式員留下來的抱怨BUG及設計失誤的話。

  >> 記憶體管理是程式設計中最經典的話題。GC無疑是記憶體管理一個偉大的變革,但是我只是把它看作記憶體管理的一個解決方案,而認為不是唯一的解決方案。比GC更加優雅的方案不見得沒有。我比較傾向於在特定的情況下選擇合適的記憶體管理方案,而不是沒有任何選擇的餘地,而這正是C/C++的偉大之處。 所有那些GC語言(如Java、C#等)均把這個解決方案強加給程式員,這一定程度上來說減輕了程式員的負擔,但是也同時約束了程式員的主觀能動性。"分配記憶體和釋放記憶體在C語言中都是很慢的"?不知道作者從哪裡獲得的結論。

  實話說我也不喜歡GC,沒有GC的C也可以工作的很好,但是對於FP系的語言來說沒有GC是無法正確工作的,所以我還是得接受GC這個東西。當然我更喜歡的是將兩者互相結合的方式。

  >> C/C++語言本身確實沒有太多MultiThead的支援,這種情況在C++0x出來後可望改變。但是,請記住C/C++永遠傾向於你使用成熟的庫來解決問題。

  C/C++不能適應未來多核時代的發展,這個會是它沒落的最大原因。庫不能真正的解決問題,我們需要的是在語言層面的進一步發展。

  >> 指標是C/C++過於靈活的體現。使用指標的代碼可以寫得很醜陋,但一樣可以很優雅。——這一點上用何種語言不會有區別。我相信,可以寫出優雅的Java代碼,那麼也一定可以寫出同樣優雅的C/C++代碼。而反之則未必(因為有些C++某些範式是Java所不能支援的)。C/C++語言中的選擇太多,這的確是令人困惑的,但不見得是劣勢。我對C/C++程式員的建議是,多瞭解和使用C++標準庫,而不是過於糾纏指標相關的細節。

  >> 演算法最佳化是程式設計的關鍵。但是通常情況下,所有語言(包括C/C++)的程式員研究的是關鍵路徑的最佳化。研究*p++是不是比p[i]快?我相信這是標準庫的實現者要考慮的事情。所不同的是,C/C++程式員也可以和標準庫的作者一樣去考慮這些細節,而其他語言的程式員被剝奪了這個權利。

  說到最佳化,話題就多了。我曾經向C#的Dictionary中插入了1億條整數(從1萬多個文字檔中讀入),結果發現程式運行了整整一個下午仍然沒有完成。而我改用C++的std::map,20分鐘就搞定了。再試試對50萬條自訂的結構體資料進行排序,我相信你和我一樣,會深深喜歡上C++的的高效而優雅。

  多年以前程式員們還在C程式裡面內聯彙編以實現代碼級的最佳化,但是如今已經沒有人這麼做了,因為CPU越來越複雜了,大多數情況編譯器做的比手工的要好。現如今的java/.NET的JIT引擎也已經能夠達到非常高的最佳化水平,在效能上C代碼的優勢已經越來越不明顯了。對於未來而言代碼級的最佳化也已經不再是重點,哪個語言可以適應多核的發展,誰就將成為效能的王者。

  >> 新生的語言,必然會在吸收舊的語言上基礎上進行改進。看一個語言的生命力,並不在於看它某些地方存在的不足。事物會發展,並趨於完善。相信C++0x出來後,C/C++語言又將獲得新的生命力。單看Java、C#等幾個新一代的語言,其中有如此多的C++烙印,就證明了C/C++的影響是巨大的。動不動說一門語言死了,是一種淺薄。

  說一門語言死了,不是說完全消失,而是退出主流開發語言行列,逐漸的被邊緣化,這些年鼓吹C/C++的人已經越來越少了,在很多開發領域C/C++的地位已經被JAVA、.net、指令碼語言等所取代。C++0x出不出來已經不重要了,倒是C++/CLI的出現帶給C++一些新意,不過雖然我很欣賞C++/CLI,但是它不會成為主流。在多核到來的時候目前程式設計語言還沒做好準備,未來我們要面臨的不是2核4核而是百核千核這樣的規模,這不光要在演算法領域繼續發展,程式設計語言也要來一次重大的變革才能適應這種發展,至於方向在哪裡,FP系的語言或許會給你帶來一些啟示。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.