與 C 語言長別離
(點選上方公眾號,可快速關注)
編譯:Linux 中國 / Yu Haixin,英文: Eric Raymond
https://linux.cn/article-9268-1.html
本文作者:埃裡克·雷蒙德(Eric Raymond),著名的計算機程式設計師,開源軟體運動的旗手。
1990年,他編輯了《新黑客字典》 。從此對黑客文化著迷,成為黑客部落的歷史學家和黑客文化的學者,1996年寫成了《黑客道簡史》。他開始把自己定位於人類學家:“人類學家的工作就是研究人的行為及整個社會,研究人類文化的形成、文化的作用方式、文化如何隨時間變化而變化,以及人類如何適應不同的文化環境等。我考慮最多的是有關計算機黑客的文化,更多地集中於從社會的角度分析,而不是他們的高超技術和程式。”
1997年5月,他完成的《大教堂和大集市》在Linux Kongress上發表,受到了空前的歡迎。這本書最大的成就就是1998年促成了網景Mozilla成為開放原始碼軟體,標準著主流商業界第一次全面認同了他的理論。因為寫作此文,讓他看到了一個全新的方向。1998年2月3日,矽谷的一次會議上,“開放原始碼(Open Source)”,由第一個參與者在會上提出,後來發展成為開源運動,並最終成為開源的發起組織。雷蒙德成了領導這場運動的理論家,成為開放原始碼促進會(Open Source Initiative)的主要創辦人之一。
---【正文】---
這幾天來,我在思考那些正在挑戰 C 語言的系統程式語言領袖地位的新潮語言,尤其是 Go 和 Rust。思考的過程中,我意識到了一個讓我震驚的事實 —— 我有著 35 年的 C 語言經驗。每週我都要寫很多 C 程式碼,但是我已經記不清楚上一次我 建立一個新的 C 語言專案 是在什麼時候了。
如果你完全不認為這種情況令人震驚,那你很可能不是一個系統程式設計師。我知道有很多程式設計師使用更高階的語言工作。但是我把大部分時間都花在了深入打磨像 NTPsec、 GPSD 以及 giflib 這些東西上。熟練使用 C 語言在這幾十年裡一直就是我的專長。但是,現在我不僅是不再使用 C 語言寫新的專案,甚至我都記不清我是什麼時候開始這樣做的了,而且……回頭想想,我覺得這都不是本世紀發生的事情。
這個對於我來說是件大事,因為如果你問我,我的五個最核心軟體開發技能是什麼,“C 語言專家” 一定是你最有可能聽到的之一。這也激起了我的思考。C 語言的未來會怎樣 ?C 語言是否正像當年的 COBOL 語言一樣,在輝煌之後,走向落幕?
我恰好是在 C 語言迅猛發展,並把組合語言以及其它許多編譯型語言擠出主流存在的前幾年開始程式設計的。那場過渡大約是在 1982 到 1985 年之間。在那之前,有很多編譯型語言爭相吸引程式設計師的注意力,那些語言中還沒有明確的領導者;但是在那之後,小眾的語言就直接毫無聲息的退出了舞臺。主流的語言(FORTRAN、Pascal、COBOL)則要麼只限於老程式碼,要麼就是固守單一領域,再就是在 C 語言的邊緣領域頂著愈來愈大的壓力苟延殘喘。
而在那以後,這種情形持續了近 30 年。儘管在應用程式開發上出現了新的動向: Java、 Perl、 Python, 以及許許多多不是很成功的競爭者。起初我很少關注這些語言,這很大一部分是因為在它們的執行時的開銷對於當時的實際硬體來說太大。因此,這就使得 C 的成功無可撼動;為了使用和對接大量已有的 C 語言程式碼,你得使用 C 語言寫新程式碼(一部分指令碼語言嘗試過打破這種壁壘,但是隻有 Python 有可能取得成功)。
回想起來,我在 1997 年使用指令碼語言寫應用時本應該注意到這些語言的更重要的意義的。當時我寫的是一個名為 SunSITE 的幫助圖書管理員做原始碼分發的輔助軟體,當時使用的是 Perl 語言。
這個應用完全是用來處理文字輸入的,而且只需要能夠應對人類的反應速度即可(大概 0.1 秒),因此使用 C 或者別的沒有動態記憶體分配以及字串型別的語言來寫就會顯得很傻。但是在當時,我僅僅是把其視為一個試驗,而完全沒有想到我幾乎再也不會在一個新專案的第一個檔案裡敲下 int main(int argc, char **argv) 這樣的 C 語言程式碼了。
我說“幾乎”,主要是因為 1999 年的 SNG。 我想那是我最後一個用 C 從頭開始寫的專案了。
在那之後我寫的所有的 C 程式碼都是在為那些上世紀已經存在的老專案添磚加瓦,或者是在維護諸如 GPSD 以及 NTPsec 一類的專案。
當年我本不應該使用 C 語言寫 SNG 的。因為在那個年代,摩爾定律的快速迭代使得硬體愈加便宜,使得像 Perl 這樣的語言的執行效率也不再是問題。僅僅三年以後,我可能就會毫不猶豫地使用 Python 而不是 C 語言來寫 SNG。
在 1997 年我學習了 Python, 這對我來說是一道分水嶺。這個語言很美妙 —— 就像我早年使用的 Lisp 一樣,而且 Python 還有很酷的庫!甚至還完全遵循了 POSIX!還有一個蠻好用的物件系統!Python 沒有把 C 語言擠出我的工具箱,但是我很快就習慣了在只要能用 Python 時就寫 Python ,而只在必須使用 C 語言時寫 C。
(在此之後,我開始在我的訪談中指出我所謂的 “Perl 的教訓” ,也就是任何一個沒能實現和 C 語言語義等價的遵循 POSIX 的語言都註定要失敗。在電腦科學的發展史上,很多學術語言的骨骸俯拾皆是,原因是這些語言的設計者沒有意識到這個重要的問題。)
顯然,對我來說,Python 的主要優勢之一就是它很簡單,當我寫 Python 時,我不再需要擔心記憶體管理問題或者會導致核心轉儲的程式崩潰 —— 對於 C 程式設計師來說,處理這些問題煩的要命。而不那麼明顯的優勢恰好在我更改語言時顯現,我在 90 年代末寫應用程式和非核心繫統服務的程式碼時,為了平衡成本與風險都會傾向於選擇具有自動記憶體管理但是開銷更大的語言,以抵消之前提到的 C 語言的缺陷。而在僅僅幾年之前(甚至是 1990 年),那些語言的開銷還是大到無法承受的;那時硬體產業的發展還在早期階段,沒有給摩爾定律足夠的時間來發揮威力。
儘量地在 C 語言和 Python 之間選擇 C —— 只要是能的話我就會從 C 語言轉移到 Python 。這是一種降低工程複雜程度的有效策略。我將這種策略應用在了 GPSD 中,而針對 NTPsec , 我對這個策略的採用則更加系統化。這就是我們能把 NTP 的程式碼庫大小削減四分之一的原因。
但是今天我不是來講 Python 的。儘管我覺得它在競爭中脫穎而出,Python 也未必真的是在 2000 年之前徹底結束我在新專案上使用 C 語言的原因,因為在當時任何一個新的學院派的動態語言都可以讓我不再選擇使用 C 語言。也有可能是在某段時間裡在我寫了很多 Java 之後,我才慢慢遠離了 C 語言。
我寫這個回憶錄是因為我覺得我並非特例,在世紀之交,同樣的發展和轉變也改變了不少 C 語言老手的編碼習慣。像我一樣,他們在當時也並沒有意識到這種轉變正在發生。
在 2000 年以後,儘管我還在使用 C/C++ 寫之前的專案,比如 GPSD ,遊戲韋諾之戰以及 NTPsec,但是我的所有新專案都是使用 Python 的。
有很多程式是在完全無法在 C 語言下寫出來的,尤其是 reposurgeon 以及 doclifter 這樣的專案。由於 C 語言受限的資料型別本體論以及其脆弱的底層資料管理問題,嘗試用 C 寫的話可能會很恐怖,並註定失敗。
甚至是對於更小的專案 —— 那些可以在 C 中實現的東西 —— 我也使用 Python 寫,因為我不想花不必要的時間以及精力去處理核心轉儲問題。這種情況一直持續到去年年底,持續到我建立我的第一個 Rust 專案,以及成功寫出第一個使用 Go 語言的專案。
如前文所述,儘管我是在討論我的個人經歷,但是我想我的經歷體現了時代的趨勢。我期待新潮流的出現,而不是僅僅跟隨潮流。在 98 年的時候,我就是 Python 的早期使用者。來自 TIOBE 的資料則表明,在 Go 語言脫胎於公司的實驗專案並剛剛從小眾語言中脫穎而出的幾個月內,我就開始實現自己的第一個 Go 語言專案了。
總而言之:直到現在第一批有可能挑戰 C 語言的傳統地位的語言才出現。我判斷這個的標準很簡單 —— 只要這個語言能讓我等 C 語言老手接受不再寫 C 的事實,這個語言才 “有可能” 挑戰到 C 語言的地位 —— 來看啊,這有個新編譯器,能把 C 轉換到新語言,現在你可以讓他完成你的全部工作了 —— 這樣 C 語言的老手就會開心起來。
Python 以及和其類似的語言對此做的並不夠好。使用 Python 實現 NTPsec(以此舉例)可能是個災難,最終會由於過高的執行時開銷以及由於垃圾回收機制導致的延遲變化而爛尾。如果需求是針對單個使用者且只需要以人類能接受的速度執行,使用 Python 當然是很好的,但是對於以 機器的速度 執行的程式來說就不總是如此了 —— 尤其是在很高的多使用者負載之下。這不只是我自己的判斷 —— 因為拿 Go 語言來說,它的存在主要就是因為當時作為 Python 語言主要支持者的 Google 在使用 Python 實現一些工程的時候也遭遇了同樣的效能痛點。
Go 語言就是為了解決 Python 搞不定的那些大多由 C 語言來實現的任務而設計的。儘管沒有一個全自動語言轉換軟體讓我很是不爽,但是使用 Go 語言來寫系統程式對我來說不算麻煩,我發現我寫 Go 寫的還挺開心的。我的很多 C 編碼技能還可以繼續使用,我還收穫了垃圾回收機制以及併發程式設計機制,這何樂而不為?
(這裡有關於我第一次寫 Go 的經驗的更多資訊 連結:https://blog.ntpsec.org/2017/02/07/grappling-with-go.html)
本來我想把 Rust 也視為 “C 語言要過時了” 的例證,但是在學習並嘗試使用了這門語言程式設計之後,我覺得這種語言現在還沒有做好準備。也許 5 年以後,它才會成為 C 語言的對手。
隨著 2017 的尾聲來臨,我們已經發現了一個相對成熟的語言,其和 C 類似,能夠勝任 C 語言的大部分工作場景(我在下面會準確描述),在幾年以後,這個語言界的新星可能就會取得成功。
這件事意義重大。如果你不長遠地回顧歷史,你可能看不出來這件事情的偉大性。三十年了 —— 這幾乎就是我作為一個程式設計師的全部生涯,我們都沒有等到一個 C 語言的繼任者,也無法遙望 C 之後的系統程式設計會是什麼樣子的。而現在,我們面前突然有了後 C 時代的兩種不同的展望和未來……
……另一種展望則是下面這個語言留給我們的。我的一個朋友正在開發一個他稱之為 “Cx” 的語言,這個語言在 C 語言上做了很少的改動,使得其能夠支援型別安全;他的專案的目的就是要建立一個能夠在最少人力參與的情況下把古典 C 語言修改為新語言的程式。我不會指出這位朋友的名字,免得給他太多壓力,讓他做出太多不切實際的保證。但是他的實現方法真的很是有意思,我會盡量給他募集資金。
現在,我們看到了可以替代 C 語言實現系統程式設計的三種不同的可能的道路。而就在兩年之前,我們的眼前還是一片漆黑。我重複一遍:這件事情意義重大。
我是在說 C 語言將要滅絕嗎?不是這樣的,在可預見的未來裡,C 語言還會是作業系統的核心程式設計以及裝置韌體程式設計的主流語言,在這些場景下,盡力壓榨硬體效能的古老規則還在奏效,儘管它可能不是那麼安全。
現在那些將要被 C 的繼任者攻破的領域就是我之前提到的我經常涉及的領域 —— 比如 GPSD 以及 NTPsec、系統服務以及那些因為歷史原因而使用 C 語言寫的程式。還有就是以 DNS 伺服器以及郵件傳輸代理 —— 那些需要以機器速度而不是人類的速度執行的系統程式。
現在我們可以對後 C 時代的未來窺見一斑,即上述這類領域的程式碼都可以使用那些具有強大記憶體安全特性的 C 語言的替代者實現。Go 、Rust 或者 Cx ,無論是哪個,都可能使 C 的存在被弱化。比如,如果我現在再來重新實現一遍 NTP ,我可能就會毫不猶豫的使用 Go 語言去完成。
覺得本文有幫助?請分享給更多人
關注「程式設計師的那些事」,提高程式設計技能
相關文章
- C語言與嵌入式C語言的區別C語言
- Java與C語言的區別?JavaC語言
- 概念區別 【編譯型語言與解釋型語言、動態型別語言與靜態型別語言、強型別語言與弱型別語言】編譯型別
- go語言與c語言的相互呼叫GoC語言
- C++和c語言的分別C++C語言
- C語言資料型別C語言資料型別
- C語言-識別符號命名C語言符號
- C語言基礎-2、字元型別C語言字元型別
- 補充:C語言列舉型別C語言型別
- C語言 列舉資料型別C語言資料型別
- 1413: C語言合法識別符號C語言符號
- C語言筆記——自定義型別C語言筆記型別
- C語言 指標與陣列C語言指標陣列
- c語言的定義與宣告C語言
- C語言與C++有聯絡,有區別,這些內容要了解!C語言
- 逍遙自在學C語言 | 變數、常量與資料型別C語言變數資料型別
- c語言-記錄閱讀《c缺陷與陷阱》C語言
- C語言C語言
- C語言的隱式型別轉換C語言型別
- C語言-變數常量資料型別C語言變數資料型別
- C語言合法識別符號 hd 2024C語言符號
- Python和C語言區別是什麼?PythonC語言
- Python和C語言有什麼區別?PythonC語言
- 聊聊C語言/C++—程式和程式語言C語言C++
- 一、程式語言簡介與C++C++
- 【C語言】氣泡排序與快速排序C語言排序
- c語言平年與閏年---@顏麓C語言
- 第一篇 C/C++基本語言型別C++型別
- 編譯語言、解釋語言與指令碼語言之間的區別編譯指令碼
- C語言如何計算陣列的長度C語言陣列
- 淺談強型別語言與弱型別語言,歡迎大家來點評型別
- C語言程式設計入門之--第四章C語言基本資料型別C語言程式設計資料型別
- C語言進階——基本資料型別01C語言資料型別
- python和c語言的區別是什麼PythonC語言
- Python和C語言有什麼區別?分析!PythonC語言
- C語言:使用函式計算兩點間的距離C語言函式
- C語言字串C語言字串
- C語言(一)C語言
- C語言: returnC語言