POSIX C和ANSI C、GNU C以及ISO C有什麼區別?

2puT發表於2016-07-18
K&RC 

1978年,丹尼斯·裡奇(Dennis Ritchie)和BrianKernighan合作出版了《C程式設計語言》的第一版。書中介紹的C語言標準也被C語言程式設計師稱作“K&RC”,第二版的書中也包含了一些ANSI C的標準。K&RC主要介紹了以下特色: 
結構(struct)型別 
長整數(long int)型別 
無符號整數(unsigned int)型別 
把運算子=+和=-改為+=和-=。因為=+和=-會使得編譯器不知道使用者要處理i = +10還是i =-10,使得處理上產生混淆。 

即使在後來ANSI C標準被提出的許多年後,K&RC仍然是許多編譯器的最低標準要求,許多老舊的編譯仍然執行K&RC的標準。 

[編輯] 
ANSI C 和 ISO C 
主條目:ANSI C 

1989年,C語言被 ANSI 標準化(ANSIX3.159-1989)。標準化的一個目的是擴充套件K&RC。這個標準包括了一些新特性。在K&R出版後,一些新特性被非官方地加到C語言中。 
void 函式 
函式返回 struct 或 union 型別 
void * 資料型別 

在ANSI標準化自己的過程中,一些新的特性被加了進去。ANSI也規定一套了標準函式庫。ANSI ISO(國際標準化組織)成立ISO/IEC JTC1/SC22/WG14 工作組,來規定國際標準的C語言。通過對ANSI標準的少量修改,最終通過了 ISO9899:1990。隨後,ISO標準被 ANSI 採納。 

傳統C語言到ANSI/ISO標準C語言的改進包括: 
增加了真正的標準庫 
新的預處理命令與特性 
函式原型允許在函式申明中指定引數型別 
一些新的關鍵字,包括 const、volatile 與 signed 
寬字元、寬字串與位元組多字元 
對約定規則、宣告和型別檢查的許多小改動與澄清 

WG14工作小組之後又於1995年,對1985年頒佈的標準做了兩處技術修訂(缺陷修復)和一個補充(擴充套件)。下面是 1995年做出的所有修改: 
3 個新的標準庫標頭檔案 iso646.h、wctype.h 和 wchar.h 
幾個新的記號與預定義巨集,用於對國際化提供更好的支援 
printf/sprintf 函式一系列新的格式程式碼 
大量的函式和一些型別與常量,用於多位元組字元和寬位元組字元 

[編輯] 
C99 
主條目:C99 

在ANSI的標準確立後,C語言的規範在一段時間內沒有大的變動,然而C++在自己的標準化建立過程中繼續發展壯大。《標準修正案一》在1995年為C語言建立了一個新標準,但是隻修正了一些C89標準中的細節和增加更多更廣得國際字符集支援。不過,這個標準引出了1999年ISO9899: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這樣的型別 
支援 <: :> <%%> %: %:%: ,等等奇怪的符號替代,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_copy 可以複製 ...的引數。 <time.h> 裡多了個 struct tmx 對struct tm 做了擴充套件 
輸入輸出對寬字元還有長整數等做了相應的支援 

但是各個公司對C99的支援所表現出來的興趣不同。當GCC和其它一些商業編譯器支援C99的大部分特性的時候,微軟和Borland卻似乎對此不感興趣。

相關文章