C語言怎麼樣?今天聊聊C語言的發展史!

2020-12-10 騰訊網

C語言發展史的點點滴滴。

任何一種新事物的出現都不是來自於偶然,而是時代所驅使的必然結果。

如果你問我:C語言有多偉大。那麼,我可能會想一下,說:多偉大我不知道,但是我知道很偉大。

這裡,我想說一句可能有點片面的話,就是:如今這世界上,凡是帶電的地方,可能都會有她(C語言)或者她的子孫的影子。

一、C語言發展史

1. 語言之父

丹尼斯·麥卡利斯泰爾·裡奇(英語:Dennis MacAlistair Ritchie,1941年9月9日-2011年10月12日),美國計算機科學家。黑客圈子通常稱他為「dmr」。他是C語言的創造者、Unix作業系統的關鍵開發者,對計算機領域產生了深遠影響,並與肯·湯普遜同為1983年圖靈獎得主。

丹尼斯.裡奇 生平時間線

麻省理工大學計算機系的馬丁教授評價說:"如果說,賈伯斯是可視化產品中的國王,那麼裡奇就是不可見王國中的君主。賈伯斯的貢獻在於,他如此了解用戶的需求和渴求,以至於創造出了讓當代人樂不思蜀的科技產品。然而,卻是裡奇先生為這些產品提供了最核心的部件,人們看不到這些部件,卻每天都在使用著。"

2. C語言的先輩

2.1BCPL語言之父

馬丁·理察德(英語:Martin Richards,1940年7月21日-),生於英國,計算機科學家,為BCPL程式語言的發明者,發展了TRIPOS作業系統。

1966年,馬丁·理察德在劍橋大學,以CPL程式語言為基礎,發明了BCPL程式語言。

2.2B語言之父

肯尼斯·藍·湯普遜(英語:Kenneth Lane Thompson,1943年2月4日-)小名肯·湯普遜(英語:Ken Thompson),美國計算機科學學者和工程師。黑客文化圈子通常稱他為「ken」。在貝爾實驗室工作期間,湯普遜設計和實現了Unix作業系統。他創造了B語言(基於BCPL) — C語言的前身,而且他是Plan 9作業系統的創造者和開發者之一。與丹尼斯·裡奇同為1983年圖靈獎得主。

2006年,湯普遜進入Google公司工作,與他人共同設計了Go語言。

一組Ken與Dennis的照片

左Ken,右Dennis

1999年獲得美國國家技術獎 [左一:Ken | 左二:Dennis | 右一:柯林頓]

從這些老照片中,我隱隱約約看到了幾行小字,寫著:

1.與優秀之人為伍

2.互相成就

試想,有多麼重要?

3. C語言時間線

從圖中時間線,可以明顯的看出C語言的起源以及時間節點。

有時候不得不說時勢造英雄,在1969~1971年之間著名的作業系統Unix從肯.湯普遜手中誕生,作為一種大型的系統性軟體來說,極其需要一種可靠的高級語言的出現(當時的低級語言指的是彙編,因為之前的作業系統是用彙編寫的)。

這個時候的丹尼斯.裡奇也沒閒著,在對B語言改良之後,就誕生了帶有類型的C語言(據裡奇自己說,有一段時間稱這種改良的語言為NB。即:new B。不過,在我們這些吃瓜群眾眼中看來也確實NB)。

4. unix時間線

Unix的誕生與C語言被廣泛的傳播、使用,有著密切的聯繫。

上圖時間線只顯示前幾個與C語言在相同時間段內誕生的Unix版本(當然,感興趣的話,可以查詢Unix相關發展史,絕對會讓你大吃一驚。其中最著名的幾個分支:BSD、minix、Linux...)。

下面,通過在網上找得到的部分Unix內核源碼,來追溯一下C語言出現的時機。

4.1 PDP-Unix

PDP-Unix系統內核代碼文件

可以看到基本都是用彙編寫的(文件名後綴.s)。為什麼用基本這個詞呢?因為,在系統裡面有一部分命令是用B語言寫的。

4.2 First Edition Unix

First Edition Unix系統內核代碼文件

可以看到,還是用彙編寫的(文件名後綴.s)。

4.3 Second Edition Unix

Second Edition Unix系統內核代碼文件

到這個版本,已經可以看到C語言的身影了。

4.4 Unix與C語言

從C語言在Unix V2版本出現之後,Unix的V3版本開始,已經可以在Unix內核中見到大量C語言編寫的代碼。

據裡奇所說:到1973年初,現代C的基本知識已經完成。C語言和編譯器強大到,足以讓我們在當年夏天用C重寫PDP-11的Unix內核 (也就是Unix的V3版本)。

到了這個時間節點,基本可以肯定的是C語言、Unix的大部分核心都已經完善。剩下要做的就是,可移植性、標準化。

後面的故事,大家可能也聽說過:後來學術和政府組織中都在使用Unix,也正是由於Unix的風靡與興盛,帶動了C語言被廣泛的傳播、使用。

在1980年代,C語言的使用廣泛傳播,並且幾乎所有機器體系結構和作業系統都可以使用編譯器。尤其是,它已成為個人計算機的編程工具,無論是用於這些機器的商業軟體製造商,還是對編程感興趣的最終用戶,都非常受歡迎。

這也就是所謂的互相成就。

一句話概括就是:不畏得失、日漸精進,最終互相成就。

5. 第一個C語言編譯器是怎樣編寫的?

不知道你有沒有想過,大家都用C語言或基於C語言的語言來寫編譯器,那麼世界上第一個C語言編譯器又是怎麼編寫的呢?這不是一個「雞和蛋」的問題……

回顧一下C語言歷史:Tomphson在BCPL的基礎上開發了B語言,Ritchie又在B語言的基礎上成功開發出了現在的C語言。在C語言被用作系統程式語言之前,Tomphson也用過B語言編寫過作業系統。可見在C語言實現以前,B語言已經可以投入實用了。因此第一個C語言編譯器的原型完全可能是用B語言或者混合B語言與PDP彙編語言編寫的。

我們現在都知道,B語言的執行效率比較低,但是如果全部用彙編語言來編寫,不僅開發周期長、維護難度大,更可怕的是失去了高級程序設計語言必需的移植性。

所以早期的C語言編譯器就採取了一個取巧的辦法:先用彙編語言編寫一個C語言的一個子集的編譯器,再通過這個子集去遞推,進而完成完整的C語言編譯器。

詳細的過程如下:先創造一個只有C語言最基本功能的子集,記作C0語言,C0語言已經足夠簡單了,可以直接用彙編語言編寫出C0的編譯器。依靠C0已有的功能,設計比C0複雜,但仍然不完整的C語言的又一個子集C1語言,其中C0屬於C1,C1屬於C,用C0開發出C1語言的編譯器。

在C1的基礎上設計C語言的又一個子集C2語言,C2語言比C1複雜,但是仍然不是完整的C語言,開發出C2語言的編譯器 …… 如此直到CN,CN已經足夠強大了,這時候就足夠開發出完整的C語言編譯器的實現了。

至於這裡的N是多少,這取決於你的目標語言(這裡是C語言)的複雜程度和程式設計師的編程能力。簡單地說,如果到了某個子集階段,可以很方便地利用現有功能實現C語言時,那麼你就找到N了。下面的圖說明了這個抽象過程:

而這個過程也在Unix V2版本中找到了證據。

肯恩·湯普森,丹尼斯·裡奇和其他人在貝爾實驗室為PDP-11開發了Unix的第二版。它通過更多的系統調用和更多的命令擴展了第一版。此版本還看到了C語言的開始,該語言用於編寫一些命令。

此處的代碼僅是某些命令,某些庫函數和C編譯器的原始碼。c /中的文件來自 last1120c.tar.gz 磁帶,並構成了第二版Unix的有效C編譯器。

二、BCPL、B、C語言

如果想要找到一種好的方式,來進行程式語言之間的比較的話,那麼非代碼莫屬。

1. 3種語言代碼示例

下面分別使用BCPL、B、C三種語言實現一個簡單的程序:程序將三個數字a、b、c相加,並將結果賦值給sum,最後列印總和。

1.1 BCPL語言示例

LET 聲明變量

:= 符號為賦值符號 Go中也有該符號,表示函數內部局部變量。這裡感覺很有意思的一點是:最初B語言之父肯.湯普遜把:=符號改成了=符號。現在,也作為Go語言之父之一,又把:=符號請回來了(冥冥之中的命運~)。

1.2 B語言示例

B語言的語言結構

B語言代碼示例

語句auto ...是一個聲明。即,它定義了要在函數內使用的局部變量。putnumb 是一個帶參數的庫函數,它將在終端上列印一個數字。

1.3 C語言示例

2. 示例代碼中三者的區別

2.1 通過上面例子可以看出三者的區別:

C語言寫法更接近於B語言

BCPL、B語言都是無類型的語言,用word/cell表示一個固定長度的bit,C語言是有類型的

2.2 有一些地方,你可能感興趣:

++、-- 符號是Thompson發明的

&&、|| 是在C語言引入的

2.3 說明:

查了好久只找到了BCPL、B語言的部分代碼片段,至於能不能跑起來,我也不知道 ^_^

如果想要知曉三者的具體區別的話,建議閱讀丹尼斯.裡奇關於《C語言發展史》的文章

BCPL、B語言也有經歷過若干次版本迭代

C語言更接近與B語言,或著說是在B的基礎上不斷的添加了很多新特性。

三、歷史為什麼選擇C語言

1960s年代後期,貝爾實驗室對計算機系統的研究進入繁盛時期。MIT、General Electric、Bell實驗室合作的Mutlics項目以失敗而告終(1969年左右)。

就是在這個時期,Ken Tompson開始寫Mutlics的替代品,他希望按照自己的設計構造一個令人舒服的計算系統(也就是Unix)。後來在寫出第一個版本的Unix時,覺得Unix上需要一個新的系統程式語言,他創造了一個B語言。B語言是沒有類型的C,準確說B語言是Tompson把BCPL擠進8K內存,被其個人大腦過濾後的產生的語言。

由於B語言存在的一些問題,導致其只是被用來寫一些命令工具使用。恰好在這個時期,Ritchie在B語言的基礎上,進行了重新的設計改良,從而誕生了C語言。

1973年,C語言基本上已經完備,從語言和編譯器層面已經足夠讓Tompson和Ritchie使用C語言重寫Unix內核。後來,Unix在一些研究機構、大學、政府機關開始慢慢流行起來,進而帶動了C語言的發展。

1978年,K&R編寫的《The C Programming Language》出版,進一步推動了C語言的普及。

用一句話總結就是:對的時間、對的地點,出現了對的人以及工具 (Unix與C語言的關係,有點像GNU與Linux kernel的關係,都是互相成就)。

四、標準C庫及代碼

C語言及其標準經過若干次迭代之後,就成了今天大家看到的樣子。其標準中指定了很多C標準庫,而不同的系統都有自己不同的代碼實現。

當然,Linux內核中也有實現了標準C庫的代碼,下面一起欣賞她的美。

1. 標準C庫

ANSI C共包括15個頭文件。1995年,(NA1)批准了3個頭文件增加到C標準函數庫中。C99標準增加6個頭文件。C11標準中又新增了5個頭文件。

至此,C標準函數庫共有29個頭文件:

2. linux/lib/string.c

下面列出3個字符串處理函數 strcpy()、strncpy()、strncat()。代碼出自Linus Benedict Torvalds之手,為什麼這麼說?看代碼頭部注釋,還是那個熟悉的味道stupid。看過git原始碼的人應該也會知道,git源碼中也有類似注釋。

五、廉頗老矣,尚能飯否

經歷過幾十年的風雨洗禮,C語言可謂風光無數,這世界上隨處可見它的身影。但是,同時在一些人眼裡,可能覺得C語言已是暮年(將近50歲)、老矣。如同下圖:

如果你真這樣想,那你就錯了。

TIOBE 2020-09 程式語言排行榜告訴你,C語言寶刀未老,還是那個風採耀眼的少年。

個人想說的是,只要計算機還是基於馮諾依曼體系結構,晶片還是基於物理製程。那麼,都會有一片C的天空。因為,她知道一個最接近天空的地方(C是最接近彙編、機器語言的高級語言之一)。

*總結:

猛然間發現已經到了總結,但是還覺得仍舊意猶未盡,這並不是我心目中最真實的那個她。但是,我還是希望你看完本文之後,能夠多少了解與熟悉C的美與真實。

相關焦點

  • 深入理解C語言
    導讀:Dennis Ritchie過世了,他發明了C語言,一個影響深遠並徹底改變世界的計算機語言。一門經歷40多年的到今天還長盛不訓的語言,今天很多語言都受到C的影響,C++,Java,C#,Perl,PHP,Javascript等等。但是,你對C了解嗎?相信你看過本站的《C語言的謎題》還有《誰說C語言很簡單?》。
  • 「C語言從入門到入土」必備C語言基礎筆記整理
    一、C語言1、什麼是C語言?C語言是人寫機器看的一種語言。C語言是高級語言中的低級語言。C語言貼近硬體。C語言的入門學習比較簡單。彙編語言——>B語言——>C語言2、C語言的特性首先C語言就是你的女朋友。無論你讓它幹什麼,它絕對不會自己找到方法。
  • C語言程序設計試題及答案
    A) 'a'&&'b' B) a<=b C) a||b+c&&b-c D) !((a<b)&&!c||1)14、設有數組定義:char array[]=「student」;則數組所佔的存貯空間為( )。
  • 開課吧:C語言現在的就業形勢如何?前景怎麼樣?
    根據近幾年的程序語言排行榜來看,C語言的排名一直很靠前,這是為什麼呢?同時 C 語言也可以像彙編語言一樣對位、字節和地址進行操作, 而這三者是計算機最基本的工作單元。第二:C語言的出現本來就是為了代替彙編從事底層操作,而目前現在所出的很多語言大都不能進行底層操作,這樣就使得C語言的地位不可動搖。
  • C語言相關文件的基本知識
    用過計算機的人,對文件都不陌生,大多數人都接觸過,今天我們來講講關於C語言相關文件的基本知識。首先,我們先來了解了解什麼是文件。文件有不同的類型,在程序的設計中,主要有兩種文件; 1.程序文件;包括源程序文件(後綴為.c),目標文件(後綴為.obj),可執行文件(後綴為.exe)等,這類文件的內容是程序代碼。
  • C語言編程:驗證哥德巴赫猜想
    大家好,我是阿湯哥,前兩天在後臺看到有朋友問驗證哥德巴赫猜想,今天我們就來看個相關的問題
  • 自考「C語言程序設計」模擬試題十一
    「c」    B.『\\』『    C.』W『   D. 』『  14.若有代數式3ae/bc,則不正確的c語言表達式是(     )  A.a/b/c*e*3    B.3*a*e/b/c    C.3*a*e/b*c    D.a*e/c/c*3  15.在C語言中,要求運算數必須是整型的運算符是(   )  A./    B.++   C
  • 如何利用C語言求二元一次方程的解
    今天,小編我來詳細的講解一節C語言的具體運用。我們今天先拿二元一次方程來開刀。大家都知道二元一次方程的解,有三種情況,即無解, 有兩個相同的解,有兩個不同的解。那麼在編程前我們先要制定流程圖,二元一次方程的係數在這裡我們依然使用我們常用的a,b,c,根的判別式,這個我們都知道b^2-4ac(其中『^』這個是指數的意思),求解公式等。
  • 剖析C語言中a=a+++a的無聊問題
    這種純屬C語言 「二」 級的問題應該是從a+++a引申出來的吧。於是乎兄弟姐妹們開始討論它的運算結果,以及改如何理解。更有人寫出(a++)+(++a) a+(++(++a)) ((a++)++)+a這樣的東西,問應該如何計算。我表示鴨梨很大...
  • C語言程序設計試題與答案B卷
    每小題1分,共20分)1、一個C語言程序是由( )。A)可構成多重循環結構 B)循環次數不可能為0C)循環次數可能為0 D)先執行後判斷17、設int x=1,a=9,b=6,c=7,d=8;則執行語句:if(a>b) if(c>d)x=2;else x=3; 後,x的值是( )。
  • ARM中ADS環境下C語言和彙編語言混合編程及示例
    下面是一個例子來說明如何在C中內嵌彙編語言  C語言文件.c httphi.baidu.comprocatlaw  #include stdio.h  void my_strcpy(const char src, char dest){  char ch;  __asm{  loop
  • C語言發展簡史
    1967 年,劍橋大學的 Matin Richards 對 CPL 語言進行了簡化,產生了 BCPL 語言。隨後不久,UNIX 的內核(Kernel) 和應用程式全部用 C 語言改寫,從此,C 語言成為 UNIX 環境下使用最廣泛的主流程式語言。
  • 自考「C語言程序設計」模擬試題九
    一、選擇題  1.一個C語言程序是由(      )構成。  A.語句          B.行號            C.數據           D.函數  2.下面標識符中正確的是(       )。
  • C語言之const和volatile"究極"學習
    const只讀變量:const修飾的變量是只讀的,本質上還是變量const修飾的局部變量在棧上分配空間const修飾的全局變量在全局數據區分配空間const只在編譯期有用,在運行期沒有用註:const修飾的變量不是真的常量,它只是告訴編譯器該變量不能出現在賦值符號的左邊2、const全局變量的分歧:在現代c語言編譯器中
  • 最全的C語言基礎知識都在這了
    我們用一個簡單的c程序例子,介紹c語言的基本構成、格式、以及良好的書寫風格,加深小夥伴們對C語言的認識。:main() { }這是c語言的基本結構,任何一個程序都必須包含這個結構。2、main()----在c語言中稱之為「主函數」,一個c程序有且僅有一個main函數,任何一個c程序總是從main函數開始執行,main函數後面的一對圓括號不能省略。3、被大括號{ }括起來的內容稱為main函數的函數體,這部分內容就是計算機要執行的內容。
  • 「記」詳解C語言之格式
    文@侍郎不是狼啦#C語言初學#在開始說明本文主題之前,我想有必要科普下C語言的歷史:C語言誕生於美國的貝爾實驗室,由D.M.Ritchie以B語言為基礎發展而來,在它的主體設計完成後,Thompson和Ritchie用它完全重寫了UNIX,且隨著UNIX的發展,c語言也得到了不斷的完善。
  • C語言中的運算符和表達式
    一、賦值運算符和賦值表達式1、賦值運算符C語言的賦值運算符為等號,表示形式「=」。此外,還有複合賦值運算符,後續陸續介紹。8、算術表達式使用算術運算符將運算對象連接起來、符合C語言語法規則的式子。五、條件運算符和條件表達式條件運算符是C語言中唯一的一個三目運算符,它需要三個操作數,條件表達式為:表達式1?表達式2:表達式3。?
  • 用C語言實現FFT算法
    } FFT(s,Num); for(i=1;i0x101;i++) { result[i]=sqrt(pow(s[i].real,2)+pow(s[i].imag,2)); }} c語言相關文章
  • 二級c語言考試改革_計算機二級考試c語言考試題型 - CSDN
    今天,想給大家介紹一下計算機二級考試的相關問題,礙於本人寫作水平有限,還望各位大佬指點。教育招生考試院的官網上在12月10日已經發布了明年3月份計算機等級考試的通告。
  • 自考「C語言程序設計」模擬試題十四
    每題1分,15-18每題1.5分,共20分)  1.可選作用戶標識符的一組標識符是(     )  A void    B c5_b8     C For     D 3a  Define    _53      -ab      DO  WORD      IF       Case     int  2.在C語言中