Ⅰ c語言的發展史
C語言,是一種通用的、過程式的編程語言,廣泛用於系統與應用軟體的開發。具有高效、靈活、功能豐富、表達力強和較高的移植性等特點,在程序員中備受青睞。
C語言是由UNIX的研製者丹尼斯·里奇(Dennis Ritchie)於1970年 由 肯·湯普遜(Ken Thompson)所研製出的B語言的基礎上發展和完善起來的。目前,C語言編譯器普遍存在於各種不同的操作系統中,例如UNIX、MS-DOS、Microsoft Windows及Linux等。C語言的設計影響了許多後來的編程語言,例如C++、Objective-C、Java、C#等。
後來於1980年代,為了避免各開發廠商用的C語言語法產生差異,由美國國家標准局(American National Standard Institution)為C語言訂定了一套完整的國際標准語法,稱為ANSI C,作為C語言的標准。1980年代至今的有關程序開發工具,一般都支持符合ANSI C的語法。
C語言是一個程序語言,設計目標是提供一種能以簡易的方式編譯、處理低級存儲器、產生少量的機器碼以及不需要任何運行環境支持便能運行的編程語言。C語言也很適合搭配匯編語言來使用。盡管C語言提供了許多低級處理的功能,但仍然保持著良好跨平台的特性,以一個標准規格寫出的C語言程序可在許多電腦平台上進行編譯,甚至包含一些嵌入式處理器(單片機或稱MCU)以及超級電腦等作業平台。
早期發展
C語言最早是由丹尼斯·里奇為了在PDP-11電腦上運行的UNIX系統所設計出來的編程語言,第一次發展在1969年到1973年之間。之所以被稱為「C」是因為C語言的很多特性是由一種更早的被稱為B語言的編程語言中發展而來。早期操作系統的核心大多由匯編語言組成,隨著C語言的發展,C語言已經可以用來編寫操作系統的核心。1973年,Unix操作系統的核心正式用C語言改寫,這是C語言第一次應用在操作系統的核心編寫上。
K&R C
1978年,丹尼斯·里奇(Dennis Ritchie)和布萊恩·柯林漢(Brian Kernighan)合作出版了《C程序設計語言》的第一版。書中介紹的C語言標准也被C語言程序員稱作「K&R C」,第二版的書中也包含了一些ANSI C的標准。K&R C主要介紹了以下特色:
結構(struct)類型
長整數(long int)類型
無符號整數(unsigned int)類型
把運算符=+和=-改為+=和-=。因為=+和=-會使得編譯器不知道用戶要處理i = -10還是i =- 10,使得處理上產生混淆。
即使在後來ANSI C標准被提出的許多年後,K&R C仍然是許多編譯器的最低標准要求,許多老舊的編譯仍然運行K&R C的標准。
ANSI C 和 ISO C
1989年,C語言被 ANSI 標准化(ANSI X3.159-1989)。標准化的一個目的是擴展K&R C。這個標准包括了一些新特性。在K&R出版後,一些新特性被非官方地加到C語言中。
void 函數
函數返回 struct 或 union 類型
void * 數據類型
在ANSI標准化自己的過程中,一些新的特性被加了進去。ANSI也規定了一套標准函數庫。ANSI ISO(國際標准化組織)成立 ISO/IEC JTC1/SC22/WG14 工作組,來規定國際標準的C語言。通過對ANSI標準的少量修改,最終通過了 ISO 9899:1990。隨後,ISO標准被 ANSI 採納。
傳統C語言到ANSI/ISO標准C語言的改進包括:
增加了真正的標准庫
新的預處理命令與特性
函數原型允許在函數申明中指定參數類型
一些新的關鍵字,包括 const、volatile 與 signed
寬字元、寬字元串與位元組多字元
對約定規則、聲明和類型檢查的許多小改動與澄清
WG14工作小組之後又於1995年,對1985年頒布的標准做了兩處技術修訂(缺陷修復)和一個補充(擴展)。下面是 1995 年做出的所有修改:
3 個新的標准庫頭文件 iso646.h、wctype.h 和 wchar.h
幾個新的記號與預定義宏,用於對國際化提供更好的支持
printf/sprintf 函數一系列新的格式代碼
大量的函數和一些類型與常量,用於多位元組字元和寬位元組字元
C99在ANSI的標准確立後,C語言的規范在一段時間內沒有大的變動,然而C++在自己的標准化創建過程中繼續發展壯大。《標准修正案一》在1995年為C語言創建了一個新標准,但是只修正了一些C89標准中的細節和增加更多更廣的國際字元集支持。不過,這個標准引出了1999年ISO 9899:1999的發表。它通常被稱為C99。C99被ANSI於2000年3月採用。
在C99中包括的特性有:
增加了對編譯器的限制,比如源程序每行要求至少支持到 4095 位元組,變數名函數名的要求支持到 63 位元組(extern 要求支持到 31)。
增強了預處理功能。例如:
宏支持取可變參數 #define Macro(...) __VA_ARGS__
使用宏的時候,允許省略參數,被省略的參數會被擴展成空串。
支持 // 開頭的單行注釋(這個特性實際上在C89的很多編譯器上已經被支持了)
增加了新關鍵字 restrict, inline, _Complex, _Imaginary, _Bool
支持 long long, long double _Complex, float _Complex 等類型
支持不定長的數組,即數組長度可以在運行時決定,比如利用變數作為數組長度。聲明時使用 int a[var] 的形式。不過考慮到效率和實現,不定長數組不能用在全局,或 struct 與 union 里。
變數聲明不必放在語句塊的開頭,for 語句提倡寫成 for(int i=0;i<100;++i) 的形式,即i 只在 for 語句塊內部有效。
允許採用(type_name){xx,xx,xx} 類似於 C++ 的構造函數的形式構造匿名的結構體。
初始化結構的時候允許對特定的元素賦值,形式為:
struct {int a[3],b;} foo[] = { [0].a = {1}, [1].a = 2 };
struct {int a, b, c, d;} foo = { .a = 1, .c = 3, 4, .b = 5} // 3,4 是對 .c,.d 賦值的
格式化字元串中,利用 \u 支持 unicode 的字元。
支持 16 進制的浮點數的描述。
printf scanf 的格式化串增加了對 long long int 類型的支持。
浮點數的內部數據描述支持了新標准,可以使用 #pragma 編譯器指令指定。
除了已有的 __line__ __file__ 以外,增加了 __func__ 得到當前的函數名。
允許編譯器化簡非常數的表達式。
修改了 / % 處理負數時的定義,這樣可以給出明確的結果,例如在C89中-22 / 7 = -3, -22 % 7 = -1 ,也可以-22 / 7= -4, -22 % 7 = 6。 而C99中明確為 -22 / 7 = -3, -22 % 7 = -1,只有一種結果。
取消了函數返回類型默認為 int 的規定。
允許 struct 定義的最後一個數組不指定其長度,寫做 [] 。
const const int i 將被當作 const int i 處理。
增加和修改了一些標准頭文件,比如定義 bool 的 <stdbool.h> ,定義一些標准長度的 int 的 <inttypes.h> ,定義復數的 <complex.h> ,定義寬字元的 <wctype.h> ,類似於泛型的數學函數 <tgmath.h>, 浮點數相關的 <fenv.h>。 在<stdarg.h> 增加了 va_ 用於復制 ... 的參數。<time.h> 里增加了 struct tmx ,對 struct tm 做了擴展。
輸入輸出對寬字元以及長整數等做了相應的支持。
Ⅱ C語言是由什麼發展而來的,它的發展歷程是怎樣的
c語言
C語言的原型ALGOL 60語言。(也稱為A語言)
1963年,劍橋大學將ALGOL 60語言發展成為CPL(Combined Programming Language)語言。 1967年,劍橋大學的Martin Richards 對CPL語言進行了簡化,於是產生了BCPL語言。
1970年,美國貝爾實驗室的Ken Thompson將BCPL進行了修改,並為它起了一個有趣的名字「B語言」。意思是將CPL語言煮干,提煉出它的精華。並且他用B語言寫了第一個UNIX操作系統。
而在1972年,B語言也給人「煮」了一下,美國貝爾實驗室的D.M.Ritchie在B語言的基礎上最終設計出了一種新的語言,他取了BCPL的第二個字母作為這種語言的名字,這就是C語言。
為了使UNIX操作系統推廣,1977年Dennis M.Ritchie 發表了不依賴於具體機器系統的C語言編譯文本《可移植的C語言編譯程序》。
1978年由美國電話電報公司(AT&T)貝爾實驗室正式發表了C語言。同時由B.W.Kernighan和D.M.Ritchie合著 c語言程序設計了著名的《The C Programming Language》一書。通常簡稱為《K&R》,也有人稱之為《K&R》標准。但是,在《K&R》中並沒有定義一個完整的標准C語言,後來由美國國家標准化協會(American National Standards Institute)在此基礎上制定了一個C語言標准,於一九八三年發表。通常稱之為ANSI C。
K&R第一版在很多語言細節上也不夠精確,對於pcc這個「參照編譯器」來說,它日益顯得不切實際;K&R甚至沒有很好表達它索要描述的語言,把後續擴展仍到了一邊。最後,C在早期項目中的使用受商業和政府合同支配,它意味著一個認可的正式標準是重要的。因此(在M. D. McIlroy的催促下),ANSI於1983年夏天,在CBEMA的領導下建立了X3J11委員會,目的是產生一個C標准。X3J11在1989年末提出了一個他們的報告[ANSI 89],後來這個標准被ISO接受為ISO/IEC 9899-1990。 1990年,國際標准化組織ISO(International Organization for Standards)接受了89 ANSI C 為I SO C 的標准(ISO9899-1990)。1994年,ISO修訂了C語言的標准。
目前流行的C語言編譯系統大多是以ANSI C為基礎進行開發的,但不同版本的C編譯系統所實現的語言功能和語法規則有略有差別
Ⅲ 計算機c語言發展歷程
起步
C語言的第一次發展在1969年到1973年之間。之所以被稱為「C」是因為C語言的很多特性是由一種更早的被稱為B語言的編程語言中發展而來。早期操作系統的核心大多由組合語言組成,隨著C語言的發展,C語言已經可以用來編寫操作系統的核心。1973年,Unix操作系統的核心正式用C語言改寫,這是C語言第一次應用在操作系統的核心編寫上。
K&R C
1978年,丹尼斯·里奇(Dennis Ritchie)和Brian Kernighan合作出版了《C程序設計語言》的第一版。書中介紹的C語言標准也被C語言程序設計師稱作「K&R C」,第二版的書中也包含了一些ANSI C的標准。K&R C主要介紹了以下特色:
* 結構(struct)類型
* 長整數(long int)類型
* 無號整數(unsigned int)類型
* 把運算符=+和=-改為+=和-=。因為=+和=-會使得編譯器不知道使用者要處理i = +10還是i =+ 10,使得處理上產生混淆。
即使在後來ANSI C標准被提出的許多年後,K&R C仍然是許多編譯器的最低標准要求,許多老舊的編譯仍然運行K&R C的標准。
ANSI C 和 ISO C(1985年)
1989 年,C 語言被 ANSI 標准化(ANSI X3.159-1989)。標准化的一個目的是擴展 K&R C。這個標准包括了一些新特性。在 K&R 出版後,一些新特性被非官方的加到 C 語言中。
* void 函數
* 函數返回 struct 或 union 類型
* void * 數據類型
* 在 ANSI 標准化自己的過程中,一些新的特性被加了進去。ANSI 也規定一套了標准函數庫。ANSI ISO(國際標准化組織)成立 ISO/IEC JTC1/SC22/WG14 工作組, 來規定國際標準的 C 語言。通過對 ANSI 標準的少量修改,最終通過了 ISO 9899:1990。隨後, ISO 標准被 ANSI 採納。
傳統 C 語言 到 ANSI/ISO 標准 C 語言 的改進包括:
* 增加了真正的標准庫
* 新的預處理命令與特性
* 函數原型允許在函數申明中指定參數類型
* 一些新的關鍵字,包括 const、volatile 與 signed
* 寬字元、寬字元串與位元組多字元
* 對約定規則、聲明和類型檢查的許多小改動與澄清
ANSI C 和 ISO C(1995年)
作為對標準的維護與更新,WG14 工作小組在 1995年, 對 1985 年頒布的標准做了兩處技術修訂(缺陷修復)和一個補充(擴展)。下面是 1995 年做出的所有修改:
* 3 個新的標准庫頭文件 iso646.h、wctype.h 和 wchar.h
* 幾個新的記號與預定義宏,用於對國際化提供更好的支持
* printf/sprintf 函數一系列新的格式代碼
* 大量的函數和一些類型與常量,用於多位元組字元和寬位元組字元
C99
它被ANSI於2000年三月採用。
在C99中包括的特性有:
* 對編譯器限制增加了,比如源程序每行要求至少支持到 4095 位元組,變數名函數名的要求支持到 63 位元組 (extern 要求支持到 31)
* 預處理增強了。例如:
o 宏支持取參數 #define Macro(...) __VA_ARGS__
o 使用宏的時候,參數如果不寫,宏里用 #,## 這樣的東西會擴展成空串。(以前會出錯的)
o 支持 // 行注釋(這個特性實際上在C89的很多編譯器上已經被支持了)
* 增加了新關鍵字 restrict, inline, _Complex, _Imaginary, _Bool
o 支持 long long, long double _Complex, float _Complex 這樣的類型
* 支持 <: :> <% %> %: %:%: ,等等奇怪的符號替代,D&E 里提過這個
* 支持了不定長的數組。數組的長度就可以用變數了。聲明類型的時候呢,就用 int a[*] 這樣的寫法。不過考慮到效率和實現,這玩意並不是一個新類型。所以就不能用在全局裡,或者 struct union 裡面,如果你用了這樣的東西,goto 語句就受限制了。
* 變數聲明不必放在語句塊的開頭,for 語句提倡這么寫 for(int i=0;i<100;++i) 就是說,int i 的聲明放在裡面,i 只在 for 裡面有效。
* 當一個類似結構的東西需要臨時構造的時候,可以用 (type_name){xx,xx,xx} 這有點像 C++ 的構造函數
初始化結構的時候現在可以這樣寫:
*
struct {int a[3], b;} hehe[] = { [0].a = {1}, [1].a = 2 };
struct {int a, b, c, d;} hehe = { .a = 1, .c = 3, 4, .b = 5} // 3,4 是對 .c,.d 賦值的
* 字元串裡面,\u 支持 unicode 的字元
* 支持 16 進制的浮點數的描述
* 所以 printf scanf 的格式化串多支持了 ll / LL (VC6 里用的 I64) 對應新的 long long 類型。
* 浮點數的內部數據描述支持了新標准,這個可以用 #pragma 編譯器指定
* 除了已經有的 __line__ __file__ 以外,又支持了一個 __func__ 可以得到當前的函數名
* 對於非常數的表達式,也允許編譯器做化簡
* 修改了對於 / % 處理負數上的定義,比如老的標准里 -22 / 7 = -3, -22 % 7 = -1 而現在 -22 / 7 = -4, -22 % 7 = 6
* 取消了不寫函數返回類型默認就是 int 的規定
* 允許 struct 定義的最後一個數組寫做 [] 不指定其長度描述
* const const int i; 將被當作 const int i; 處理
* 增加和修改了一些標准頭文件, 比如定義 bool 的 <stdbool.h> 定義一些標准長度的 int 的 <inttypes.h> 定義*復數的 <complex.h> 定義寬字元的 <wctype.h> 有點泛型味道的數學函數 <tgmath.h> 跟浮點數有關的 <fenv.h>。<stdarg.h> 里多了一個 va_ 可以復制 ... 的參數。<time.h> 里多了個 struct tmx 對 struct tm 做了擴展
* 輸入輸出對寬字元還有長整數等做了相應的支持
* 但是各個公司對C99的支持所表現出來的興趣不同。當GCC和其它一些商業編譯器支持C99的大部分特性的時候,微軟和Borland卻似乎對此不感興趣。
Ⅳ C語言文件的編譯與執行的四個階段並分別描述
開發C程序有四個步驟:編輯、編譯、連接和運行。
任何一個體系結構處理器上都可以使用C語言程序,只要該體系結構處理器有相應的C語言編譯器和庫,那麼C源代碼就可以編譯並連接到目標二進制文件上運行。
1、預處理:導入源程序並保存(C文件)。
2、編譯:將源程序轉換為目標文件(Obj文件)。
3、鏈接:將目標文件生成為可執行文件(EXE文件)。
4、運行:執行,獲取運行結果的EXE文件。
(4)c編譯器的發展過程擴展閱讀:
將C語言代碼分為程序的幾個階段:
1、首先,源代碼文件測試。以及相關的頭文件,比如stdio。H、由預處理器CPP預處理為.I文件。預編譯的。文件不包含任何宏定義,因為所有宏都已展開,並且包含的文件已插入。我歸檔。
2、編譯過程是對預處理文件進行詞法分析、語法分析、語義分析和優化,生成相應的匯編代碼文件。這個過程往往是整個程序的核心部分,也是最復雜的部分之一。
3、匯編程序不直接輸出可執行文件,而是輸出目標文件。匯編程序可以調用LD來生成可以運行的可執行程序。也就是說,您需要鏈接大量的文件才能獲得「a.out」,即最終的可執行文件。
4、在鏈接過程中,需要重新調整其他目標文件中定義的函數調用指令,而其他目標文件中定義的變數也存在同樣的問題。
Ⅳ 最早的C語言編譯器是什麼做的
匯編。這真的是最早最早的。
准確的來說,這和編譯器的開發有關,不用說太細,很麻煩怕你不懂。你現在假設第一個編譯器是用會變寫出來的,它的功能很簡單,就是解釋簡單一種類似於C語言的高級語言,但是這種所謂的高級語言還沒有完全擁有C語言的所有特性。只有比較簡單核心功能,比如能把文本文件的高級語言轉換成機器代碼並且執行。
有了這個原型之後,就可以用這個編譯器來解釋簡單C程序,就可以用C重寫編寫一個新的編譯器,這樣就有更多的C的功能。於是,從此之後就用現有的編譯器解釋更復雜的語言,用更復雜的語言寫出更好的編譯器,然後不斷這樣迭代。這確實是編譯器的演變。
然後最後一個問題就是當一個新的CPU發明過後,怎麼辦,需要重寫又從匯編開始寫編譯器嗎?答案是不用。假設你有一個CPU A執行一些代碼,你用匯編寫了一個基礎的C編譯器,然後用C寫出了更復雜的編譯器,接受更復雜的C功能,然後不斷循環演化。現在你有了CPU B,CPU B和CPU A執行兩套完全不同的代碼,那如何讓CPU B的機器也可以變異C語言呢?因為現在A上面已經可以運行非常復雜的C語言程序了,所以你可以在A上面開發一個編譯器把C語言程序轉化為CPU B的執行代碼。然後用這個程序,直接編譯你的C語言編譯器,再把這個程序轉換到有B命令集的電腦上面,這樣你就開發出了B電腦需要的C語言編譯器。
所以除非你真的是活在非常早起的人類。否在現在的編譯器基本上都利用這種原理直接編譯已經用C語言或者其它高級語言寫好的代碼來產生新的編譯器就行了。理論上可以只使用C語言來開發C的編譯器,不過處於一些歷史原因和底層效率等因素的考量,部分代碼還是使用匯編來實現的。
我舉得不過是一個例子,不一定是真實的C語言編譯的進化,何況有這么多不同的C語言編譯器,每一個的發展歷史都有小的不同。但是基本上都是利用了這種編譯器編譯新的編譯器的思想來實現了。而這樣回溯回去,最早的編譯器只能使用匯編來些。而其實最早的匯編語言的編譯器就只能使用機器語言來寫了。不過都是先處理簡單的轉換任務,有了這個核心功能過後,就可以寫程序轉換更復雜的語法。然後越來越復雜。就有了各種各樣的高級語言編譯器了。
Ⅵ 編譯器的發展史
編譯器
編譯器,是將便於人編寫,閱讀,維護的高級計算機語言翻譯為計算機能識別,運行的低級機器語言的程序。編譯器將源程序(Source program)作為輸入,翻譯產生使用目標語言(Target language)的等價程序。源程序一般為高級語言(High-level language),如Pascal,C++等,而目標語言則是匯編語言或目標機器的目標代碼(Object code),有時也稱作機器代碼(Machine code)。
一個現代編譯器的主要工作流程如下:
源程序(source code)→預處理器(preprocessor)→編譯器(compiler)→匯編程序(assembler)→目標程序(object code)→連接器(鏈接器,Linker)→可執行程序(executables)
目錄 [隱藏]
1 工作原理
2 編譯器種類
3 預處理器(preprocessor)
4 編譯器前端(frontend)
5 編譯器後端(backend)
6 編譯語言與解釋語言對比
7 歷史
8 參見
工作原理
翻譯是從源代碼(通常為高級語言)到能直接被計算機或虛擬機執行的目標代碼(通常為低級語言或機器言)。然而,也存在從低級語言到高級語言的編譯器,這類編譯器中用來從由高級語言生成的低級語言代碼重新生成高級語言代碼的又被叫做反編譯器。也有從一種高級語言生成另一種高級語言的編譯器,或者生成一種需要進一步處理的的中間代碼的編譯器(又叫級聯)。
典型的編譯器輸出是由包含入口點的名字和地址以及外部調用(到不在這個目標文件中的函數調用)的機器代碼所組成的目標文件。一組目標文件,不必是同一編譯器產生,但使用的編譯器必需採用同樣的輸出格式,可以鏈接在一起並生成可以由用戶直接執行的可執行程序。
編譯器種類
編譯器可以生成用來在與編譯器本身所在的計算機和操作系統(平台)相同的環境下運行的目標代碼,這種編譯器又叫做「本地」編譯器。另外,編譯器也可以生成用來在其它平台上運行的目標代碼,這種編譯器又叫做交叉編譯器。交叉編譯器在生成新的硬體平台時非常有用。「源碼到源碼編譯器」是指用一種高級語言作為輸入,輸出也是高級語言的編譯器。例如: 自動並行化編譯器經常採用一種高級語言作為輸入,轉換其中的代碼,並用並行代碼注釋對它進行注釋(如OpenMP)或者用語言構造進行注釋(如FORTRAN的DOALL指令)。
預處理器(preprocessor)
作用是通過代入預定義等程序段將源程序補充完整。
編譯器前端(frontend)
前端主要負責解析(parse)輸入的源程序,由詞法分析器和語法分析器協同工作。詞法分析器負責把源程序中的『單詞』(Token)找出來,語法分析器把這些分散的單詞按預先定義好的語法組裝成有意義的表達式,語句 ,函數等等。 例如「a = b + c;」前端詞法分析器看到的是「a, =, b , +, c;」,語法分析器按定義的語法,先把他們組裝成表達式「b + c」,再組裝成「a = b + c」的語句。 前端還負責語義(semantic checking)的檢查,例如檢測參與運算的變數是否是同一類型的,簡單的錯誤處理。最終的結果常常是一個抽象的語法樹(abstract syntax tree,或 AST),這樣後端可以在此基礎上進一步優化,處理。
編譯器後端(backend)
編譯器後端主要負責分析,優化中間代碼(Intermediate representation)以及生成機器代碼(Code Generation)。
一般說來所有的編譯器分析,優化,變型都可以分成兩大類: 函數內(intraproceral)還是函數之間(interproceral)進行。很明顯,函數間的分析,優化更准確,但需要更長的時間來完成。
編譯器分析(compiler analysis)的對象是前端生成並傳遞過來的中間代碼,現代的優化型編譯器(optimizing compiler)常常用好幾種層次的中間代碼來表示程序,高層的中間代碼(high level IR)接近輸入的源程序的格式,與輸入語言相關(language dependent),包含更多的全局性的信息,和源程序的結構;中層的中間代碼(middle level IR)與輸入語言無關,低層的中間代碼(Low level IR)與機器語言類似。 不同的分析,優化發生在最適合的那一層中間代碼上。
常見的編譯分析有函數調用樹(call tree),控制流程圖(Control flow graph),以及在此基礎上的 變數定義-使用,使用-定義鏈(define-use/use-define or u-d/d-u chain),變數別名分析(alias analysis),指針分析(pointer analysis),數據依賴分析(data dependence analysis)等等。
上述的程序分析結果是編譯器優化(compiler optimization)和程序變形(compiler transformation)的前提條件。常見的優化和變新有:函數內嵌(inlining),無用代碼刪除(Dead code elimination),標准化循環結構(loop normalization),循環體展開(loop unrolling),循環體合並,分裂(loop fusion,loop fission),數組填充(array padding),等等。 優化和變形的目的是減少代碼的長度,提高內存(memory),緩存(cache)的使用率,減少讀寫磁碟,訪問網路數據的頻率。更高級的優化甚至可以把序列化的代碼(serial code)變成並行運算,多線程的代碼(parallelized,multi-threaded code)。
機器代碼的生成是優化變型後的中間代碼轉換成機器指令的過程。現代編譯器主要採用生成匯編代碼(assembly code)的策略,而不直接生成二進制的目標代碼(binary object code)。即使在代碼生成階段,高級編譯器仍然要做很多分析,優化,變形的工作。例如如何分配寄存器(register allocatioin),如何選擇合適的機器指令(instruction selection),如何合並幾句代碼成一句等等。
編譯語言與解釋語言對比
許多人將高級程序語言分為兩類: 編譯型語言 和 解釋型語言 。然而,實際上,這些語言中的大多數既可用編譯型實現也可用解釋型實現,分類實際上反映的是那種語言常見的實現方式。(但是,某些解釋型語言,很難用編譯型實現。比如那些允許 在線代碼更改 的解釋型語言。)
歷史
上世紀50年代,IBM的John Backus帶領一個研究小組對FORTRAN語言及其編譯器進行開發。但由於當時人們對編譯理論了解不多,開發工作變得既復雜又艱苦。與此同時,Noam Chomsky開始了他對自然語言結構的研究。他的發現最終使得編譯器的結構異常簡單,甚至還帶有了一些自動化。Chomsky的研究導致了根據語言文法的難易程度以及識別它們所需要的演算法來對語言分類。正如現在所稱的Chomsky架構(Chomsky Hierarchy),它包括了文法的四個層次:0型文法、1型文法、2型文法和3型文法,且其中的每一個都是其前者的特殊情況。2型文法(或上下文無關文法)被證明是程序設計語言中最有用的,而且今天它已代表著程序設計語言結構的標准方式。分析問題(parsing problem,用於上下文無關文法識別的有效演算法)的研究是在60年代和70年代,它相當完善的解決了這個問題。現在它已是編譯原理中的一個標准部分。
有限狀態自動機(Finite Automaton)和正則表達式(Regular Expression)同上下文無關文法緊密相關,它們與Chomsky的3型文法相對應。對它們的研究與Chomsky的研究幾乎同時開始,並且引出了表示程序設計語言的單詞的符號方式。
人們接著又深化了生成有效目標代碼的方法,這就是最初的編譯器,它們被一直使用至今。人們通常將其稱為優化技術(Optimization Technique),但因其從未真正地得到過被優化了的目標代碼而僅僅改進了它的有效性,因此實際上應稱作代碼改進技術(Code Improvement Technique)。
當分析問題變得好懂起來時,人們就在開發程序上花費了很大的功夫來研究這一部分的編譯器自動構造。這些程序最初被稱為編譯器的編譯器(Compiler-compiler),但更確切地應稱為分析程序生成器(Parser Generator),這是因為它們僅僅能夠自動處理編譯的一部分。這些程序中最著名的是Yacc(Yet Another Compiler-compiler),它是由Steve Johnson在1975年為Unix系統編寫的。類似的,有限狀態自動機的研究也發展了一種稱為掃描程序生成器(Scanner Generator)的工具,Lex(與Yacc同時,由Mike Lesk為Unix系統開發)是這其中的佼佼者。
在70年代後期和80年代早期,大量的項目都貫注於編譯器其它部分的生成自動化,這其中就包括了代碼生成。這些嘗試並未取得多少成功,這大概是因為操作太復雜而人們又對其不甚了解。
編譯器設計最近的發展包括:首先,編譯器包括了更加復雜演算法的應用程序它用於推斷或簡化程序中的信息;這又與更為復雜的程序設計語言的發展結合在一起。其中典型的有用於函數語言編譯的Hindley-Milner類型檢查的統一演算法。其次,編譯器已越來越成為基於窗口的交互開發環境(Interactive Development Environment,IDE)的一部分,它包括了編輯器、連接程序、調試程序以及項目管理程序。這樣的IDE標准並沒有多少,但是對標準的窗口環境進行開發已成為方向。另一方面,盡管近年來在編譯原理領域進行了大量的研究,但是基本的編譯器設計原理在近20年中都沒有多大的改變,它現在正迅速地成為計算機科學課程中的中心環節。
在九十年代,作為GNU項目或其它開放源代碼項目的一部分,許多免費編譯器和編譯器開發工具被開發出來。這些工具可用來編譯所有的計算機程序語言。它們中的一些項目被認為是高質量的,而且對現代編譯理論感性趣的人可以很容易的得到它們的免費源代碼。
大約在1999年,SGI公布了他們的一個工業化的並行化優化編譯器Pro64的源代碼,後被全世界多個編譯器研究小組用來做研究平台,並命名為Open64。Open64的設計結構好,分析優化全面,是編譯器高級研究的理想平台。
編譯器是一種特殊的程序,它可以把以特定編程語言寫成的程序變為機器可以運行的機器碼。我們把一個程序寫好,這時我們利用的環境是文本編輯器。這時我程序把程序稱為源程序。在此以後程序員可以運行相應的編譯器,通過指定需要編譯的文件的名稱就可以把相應的源文件(通過一個復雜的過程)轉化為機器碼了。
編譯器工作方法
首先編譯器進行語法分析,也就是要把那些字元串分離出來。然後進行語義分析,就是把各個由語法分析分析出的語法單元的意義搞清楚。最後生成的是目標文件,我們也稱為obj文件。再經過鏈接器的鏈接就可以生成最後的可執行代碼了。有些時候我們需要把多個文件產生的目標文件進行鏈接,產生最後的代碼。我們把一過程稱為交叉鏈接。
Ⅶ C語言的發展史
發展史:
C語言的祖先是BCPL語言。
1967年,劍橋大學的 Martin Richards 對CPL語言進行了簡化,於是產生了BCPL(Basic Combined Pogramming Language)語言。
1970年,美國貝爾實驗室的 Ken Thompson。以BCPL語言為基礎,設計出很簡單且很接近硬體的B語言(取BCPL的首字母)。並且他用B語言寫了第一個UNIX操作系統。
在1972年,美國貝爾實驗室的 D.M.Ritchie 在B語言的基礎上最終設計出了一種新的語言,他取了BCPL的第二個字母作為這種語言的名字,這就是C語言。
為了使UNIX操作系統推廣,1977年Dennis M.Ritchie發表了不依賴於具體機器系統的C語言編譯文本《可移植的C語言編譯程序》。
1978年由美國電話電報公司(AT&T)貝爾實驗室正式發表了C語言。
1990年,國際標准化組織ISO(International Organization for Standards)接受了89 ANSI C 為I SO C 的標准(ISO9899-1990)。
1994年,ISO修訂了C語言的標准。
1995年,ISO對C90做了一些修訂,即「1995基準增補1(ISO/IEC/9899/AMD1:1995)」。
1999年,ISO有對C語言標准進行修訂,在基本保留原來C語言特徵的基礎上,針對應該的需要,增加了一些功能,尤其是對C++中的一些功能,命名為ISO/IEC9899:1999。
2001年和2004年先後進行了兩次技術修正。
目前流行的C語言編譯系統大多是以ANSI C為基礎進行開發的,但不同版本的C編譯系統所實現的語言功能和語法規則有略有差別。
Ⅷ 簡述c語言的發展史
C語言的祖先是BCPL語言。
1967年,劍橋大學的 Martin Richards 對CPL語言進行了簡化,於是產生了BCPL(Basic Combined Programming Language)語言。
1970年,美國貝爾實驗室的 Ken Thompson。以BCPL語言為基礎,設計出很簡單且很接近硬體的B語言(取BCPL的首字母)。並且他用B語言寫了第一個UNIX操作系統。
在1972年,美國貝爾實驗室的 D.M.Ritchie 在B語言的基礎上最終設計出了一種新的語言,他取了BCPL的第二個字母作為這種語言的名字,這就是C語言。
為了使UNIX操作系統推廣,1977年Dennis M.Ritchie發表了不依賴於具體機器系統的C語言編譯文本《可移植的C語言編譯程序》。
1978年由美國電話電報公司(AT&T)貝爾實驗室正式發表了C語言。同時由B.W.Kernighan和D.M.Ritchie合著了著名的《The C Programming Language》一書。通常簡稱為《K&R》,也有人稱之為《K&R》標准。但是,在《K&R》中並沒有定義一個完整的標准C語言,後來由美國國家標准化協會(American National Standards Institute)在此基礎上制定了一個C語言標准,於一九八三年發表。通常稱之為ANSI C。
K&R第一版在很多語言細節上也不夠精確,對於pcc這個「參照編譯器」來說,它日益顯得不切實際;K&R甚至沒有很好表達它所要描述的語言,把後續擴展扔到了一邊。最後,C在早期項目中的使用受商業和政府合同支配,這意味著一個認可的正式標準是必需的。因此(在M. D. McIlroy的催促下),ANSI於1983年夏天,在CBEMA的領導下建立了X3J11委員會,目的是產生一個C標准。X3J11在1989年末提出了一個他們的報告[ANSI 89],後來這個標准被ISO接受為ISO/IEC 9899-1990。
1990年,國際標准化組織ISO(International Organization for Standards)接受了89 ANSI C 為I SO C 的標准(ISO9899-1990)。1994年,ISO修訂了C語言的標准。
1995年,ISO對C90做了一些修訂,即「1995基準增補1(ISO/IEC/9899/AMD1:1995)」。1999年,ISO又對C語言標准進行修訂,在基本保留原來C語言特徵的基礎上,針對應該的需要,增加了一些功能,尤其是對C++中的一些功能,命名為ISO/IEC9899:1999。
2001年和2004年先後進行了兩次技術修正。
目前流行的C語言編譯系統大多是以ANSI C為基礎進行開發的,但不同版本的C編譯系統所實現的語言功能和語法規則又略有差別。
2011年12月8日,ISO正式公布C語言新的國際標准草案:ISO/IEC 9899:2011,即C11。
新的標准修提高了對C++的兼容性,並將新的特性增加到C語言中。新功能包括支持多線程, 基於ISO/IEC TR 19769:2004規范下支持Unicode,提供更多用於查詢浮點數類型特性的宏定義和靜態聲明功能。這些新特性包括:
● 對齊處理(Alignment)的標准化(包括_Alignas標志符,alignof運算符,aligned_alloc函數以及<stdalign.h>頭文件。
● _Noreturn 函數標記,類似於 gcc 的 __attribute__((noreturn))。
● _Generic 關鍵字。
● 多線程(Multithreading)支持,包括:_Thread_local存儲類型標識符,<threads.h>;頭文件,裡麵包含了線程的創建和管理函數。
● 增強的Unicode的支持。基於C Unicode技術報告ISO/IEC TR 19769:2004,增強了對Unicode的支持。包括為UTF-16/UTF-32編碼增加了char16_t和char32_t數據類型,提供了包含unicode字元串轉換函數的頭文件<uchar.h>.
● 刪除了 gets() 函數,使用一個新的更安全的函數gets_s()替代。
● 增加了邊界檢查函數介面,定義了新的安全的函數,例如 fopen_s(),strcat_s() 等等。
● 增加了更多浮點處理宏。
● 匿名結構體/聯合體支持。這個在gcc早已存在,C11將其引入標准。
● 靜態斷言(Static assertions),_Static_assert(),在解釋 #if 和 #error 之後被處理。
● 新的 fopen() 模式,(「…x」)。類似 POSIX 中的 O_CREAT|O_EXCL,在文件鎖中比較常用。
● 新增 quick_exit() 函數作為第三種終止程序的方式。當 exit()失敗時可以做最少的清理工作。
● _Atomic類型修飾符和<stdatomic.h>;頭文件。
Ⅸ 第一個 C 語言編譯器是怎樣編寫的
C 語言誕生的基本過程就是 Ken Thomson 不滿意 BCPL,於是設計了 B 語言,並且用 BCPL 為 B 語言寫了一個編譯器,然後從這個編譯器開始自舉寫新的 B 語言編譯器。貝爾實驗室的眾人在 PDP-7 上用 B 語言寫了各種各樣的東西後又不滿意 B 語言了,於是 1971 年 DMR 開始在新買的 PDP-11 上用 B 給 B 寫擴展,稱之為 NB (new B,此處省略吐槽若干),擴展著擴展著離 B 的畫風越來越遠了,就取了一個新名字變成了一門新語言—— C 語言。 1973 年夏天他們用手頭的編譯器和語言給 PDP-11 重寫了一個 Unix Kernel。C 語言大約就是這個時期成型的。
所以,可以說第一個 C 語言的編譯器是用 B 語言,或者說是擴展過的 B 語言(NB)寫的。