天天看點

C89和C99标準對比

http://blog.csdn.net/phlexii/archive/2006/06/30/855263.aspx

GCC 支援C99,通過 --std = c99指令行參數開啟。 例如:gcc --std = c99 test.c 

 

  1、增加restrict指針

   C99中增加了公适用于指針的restrict類型修飾符,它是初始通路指針所指對象的惟一途徑,是以隻有借助restrict指針表達式才能通路對 象。restrict指針指針主要用做函數變元,或者指向由malloc()函數所配置設定的記憶體變量。restrict資料類型不改變程式的語義。

  如果某個函數定義了兩個restrict指針變元,編譯程式就假定它們指向兩個不同的對象,memcpy()函數就是restrict指針的一個典型應用示例。C89中memcpy()函數原型如下:

代碼:

  void *memcpy (void *s1, const void *s2, size_t size);
  
      

     如果s1和s2所指向的對象重疊,其操作就是未定義的。memcpy()函數隻能用于不重疊的對象 。C99中memcpy()函數原型如下: 代碼:

  
   

  void *memcpy(void *restrict s1, const void *restrict s2,size_t size);
  
      

  通過使用restrict修飾s1和s2 變元,可確定它們在該原型中指向不同的對象。

 2、inline(内聯)關鍵字

   内聯函數除了保持結構化和函數式的定義方式外,還能使程式員寫出高效率的代碼.函數的每次調用與傳回都會消耗相當大的系統資源,尤其是當函數調用發生在 重複次數很多的循環語句中時.一般情況下,當發生一次函數調用時,變元需要進棧,各種寄存器記憶體需要儲存.當函數傳回時,寄存器的内容需要恢複。如果該函 數在代碼内進行聯機擴充,當代碼執行時,這些儲存和恢複操作旅遊活動會再發生,而且函數調用的執行速度也會大大加快。函數的聯機擴充會産生較長的代碼,是以隻應該内聯對應用程式性能有顯著影響的函數以及長度較短的函數

   3、新增資料類型 

  _Bool 

  值是0或1。C99中增加了用來定義bool、true以及false宏的頭檔案夾<stdbool.h>,以便程式員能夠編寫同時相容于C與C++的應用程式。在編寫新的應用程式時,應該使用

<stdbool.h>頭檔案中的bool宏。

  _Complex and _Imaginary

 C99标準中定義的複數類型如下:float_Complex; float_Imaginary; double_Complex; double_Imaginary; long double_Complex; long double_Imaginary.

<complex.h>頭檔案中定義了complex和imaginary宏,并将它們擴充為_Complex和_Imaginary,是以在編寫新的應用程式時,應該使用<stdbool.h>頭檔案中的complex和imaginary宏。

  long long int

  C99标準中引進了long long int(-(2e63 - 1)至2e63 - 1)和unsigned long long int(0 - 2e64 - 1)。long long int能夠支援的整數長度為64位。

 4、對數組的增強

  可變長數組

  C99中,程式員聲明數組時,數組的維數可以由任一有效的整型表達式确定,包括隻在運作時才能确定其值的表達式,這類數組就叫做可變長數組,但是隻有局部數組才可以是變長的.

可變長數組的維數在數組生存期内是不變的,也就是說,可變長數組不是動态的.可以變化的隻是數組的大小.可以使用*來定義不确定長的可變長數組。

  

  數組聲明中的類型修飾符

   在C99中,如果需要使用數組作為函數變元,可以在數組聲明的方括号内使用static關鍵字,這相當于告訴編譯程式,變元所指向的數組将至少包含指定 的元素個數。也可以在數組聲明的方括号内使用restrict,volatile,const關鍵字,但隻用于函數變元。如果使用restrict,指針 是初始通路該對象的惟一途徑。如果使用const,指針始終指向同一個數組。使用volatile沒有任何意義。

   5、單行注釋

  引入了單行注釋标記 "//" , 可以象C++一樣使用這種注釋了。

  6、分散代碼與聲明

   7、預處理程式的修改

  a、變元清單

  宏可以帶變元,在宏定義中用省略号(...)表示。内部預處理辨別符__VA_ARGS__決定變元将在何處得到替換。例:#define MySum(...) sum(__VA_ARGS__) 語句MySum(k,m,n);

将 被轉換成:sum(k, m, n); 變元還可以包含變元。例: #define compare(compf, ...) compf(__VA_ARGS__) 其中的compare(strcmp,"small", "large"); 将替換成:strcmp("small","large");

  b、_Pragma運算符

  C99引入了在程式中定義編譯指令的另外一種方法:_Pragma運算符。格式如下:

  _Pragma("directive")

  其中directive是要滿打滿算的編譯指令。_Pragma運算符允許編譯指令參與宏替換。

  c、内部編譯指令

  STDCFP_CONTRACT ON/OFF/DEFAULT 若為ON,浮點表達式被當做基于硬體方式處理的獨立單元。預設值是定義的工具。

  STDCFEVN_ACCESS ON/OFF/DEFAULT 告訴編譯程式可以通路浮點環境。預設值是定義的工具。

  STDC CX_LIMITED_RANGE ON/OFF/DEFAULT 若值為ON,相當于告訴編譯程式某程式某些含有複數的公式是可靠的。預設是OFF。

  d、新增的内部宏

  __STDC_HOSTED__ 若作業系統存在,則為1

  __STDC_VERSION__ 199991L或更高。代表C的版本

  __STDC_IEC_599__ 若支援IEC 60559浮點運算,則為1

  __STDC_IEC_599_COMPLEX__ 若支援IEC 60599複數運算,則為1

  __STDC_ISO_10646__ 由編譯程式支援,用于說明ISO/IEC 10646标準的年和月格式:yyymmmL

   9、複合指派

  C99中,複合指派中,可以指定對象類型的數組、結構或聯合表達式。當使用複合指派時,應在括弧内指定類型,後跟由花括号圍起來的初始化清單;若類型為數組,則不能指定數組的大小。建成的對象是未命名的。

  例: double *fp = (double[]) {1.1, 2.2, 3.3};

  該語句用于建立一個指向double的指針fp,且該指針指向這個3元素數組的第一個元素。 在檔案域内建立的複合指派隻在程式的整個生存期内有效。在子產品内建立的複合指派是局部對象,在退出子產品後不再存在。

  10、柔性數組結構成員

   C99中,結構中的最後一個元素允許是未知大小的數組,這就叫做柔性數組成員,但結構中的柔性數組成員前面必須至少一個其他成員。柔性數組成員允許結構 中包含一個大小可變的數組。sizeof傳回的這種結構大小不包括柔性數組的記憶體。包含柔性數組成員的結構用malloc()函數進行記憶體的動态配置設定,并 且配置設定的記憶體應該大于結構的大小,以适應柔性數組的預期大小。

  11、指定的初始化符

  C99中,該特性對經常使用稀疏數組的程式員十分有用。指定的初始化符通常有兩種用法:用于數組,以及用于結構和聯合。用于數組的格式:[index] = vol; 其中,index表示數組的下标,vol表示本數組元素的初始化值。

  例如: int x[10] = {[0] = 10, [5] = 30}; 其中隻有x[0]和x[5]得到了初始化.用于結構或聯合的格式如下:

  member-name(成員名稱)

  對結構進行指定的初始化時,允許采用簡單的方法對結構中的指定成員進行初始化。

  例如: struct example{ int k, m, n; } object = {m = 10,n = 200};

  其中,沒有初始化k。對結構成員進行初始化的順序沒有限制。

   12、printf()和scanf()函數系列的增強

   C99中printf()和scanf()函數系列引進了處理long long int和unsigned long long int資料類型的特性。long long int 類型的格式修飾符是ll。在printf()和scanf()函數中,ll适用于d, i, o, u 和x格式說明符。另外,C99還引進了hh修飾符。當使用d, i, o, u和x格式說明符時,hh用于指定char型變元。ll和hh修飾符均可以用于n說明符。

  格式修飾符a和A用在printf()函數中時,結 果将會輸出十六進制的浮點數。格式如下:[-]0xh, hhhhp + d 使用A格式修飾符時,x和p必須是大寫。A和a格式修飾符也可以用在scanf()函數中,用于讀取浮點數。調用printf()函數時,允許在%f說明 符前加上l修飾符,即%lf,但不起作用。

  13、C99新增的庫

  

  C89中标準的頭檔案

  <assert.h> 定義宏assert()

  <ctype.h> 字元處理

  <errno.h> 錯誤報告

  <float.h> 定義與實作相關的浮點值勤

  <limits.h> 定義與實作相關的各種極限值

  <locale.h> 支援函數setlocale()

  <math.h> 數學函數庫使用的各種定義

  <setjmp.h> 支援非局部跳轉

  <signal.h> 定義信号值

  <stdarg.h> 支援可變長度的變元清單

  <stddef.h> 定義常用常數

  <stdio.h> 支援檔案輸入和輸出

  <stdlib.h> 其他各種聲明

  <string.h> 支援串函數

  <time.h> 支援系統時間函數

  C99新增的頭檔案和庫

  <complex.h> 支援複數算法

  <fenv.h> 給出對浮點狀态标記和浮點環境的其他方面的通路

  <inttypes.h> 定義标準的、可移植的整型類型集合。也支援處理最大寬度整數的函數

  <iso646.h> 首先在此1995年第一次修訂時引進,用于定義對應各種運算符的宏

  <stdbool.h> 支援布爾資料類型類型。定義宏bool,以便相容于C++

  <stdint.h> 定義标準的、可移植的整型類型集合。該檔案包含在<inttypes.h>中

  <tgmath.h> 定義一般類型的浮點宏

  <wchar.h> 首先在1995年第一次修訂時引進,用于支援多位元組和寬位元組函數

  <wctype.h> 首先在1995年第一次修訂時引進,用于支援多位元組和寬位元組分類函數

  14、__func__預定義辨別符

  用于指出__func__所存放的函數名,類似于字元串指派。

  15、其它特性的改動

  放寬的轉換限制

 

    限制             C89标準  C99标準

    資料塊的嵌套層數       15     127

    條件語句的嵌套層數      8      63

    内部辨別符中的有效字元個數  31     63

    外部辨別符中的有效字元個數  6      31

    結構或聯合中的成員個數    127    1023

    函數調用中的參數個數     31     127

  不再支援隐含式的int規則

  删除了隐含式函數聲明

  對傳回值的限制

    C99中,非空類型函數必須使用帶傳回值的return語句.

  擴充的整數類型

    擴充類型 含義

    int16_t 整數長度為精确16位

    int_least16_t 整數長度為至少16位

    int_fast32_t 最穩固的整數類型,其長度為至少32位

    intmax_t 最大整數類型

    uintmax_t 最大無符号整數類型

  對整數類型提升規則的改進

    C89中,表達式中類型為char,short int或int的值可以提升為int或unsigned int類型.

    C99中,每種整數類型都有一個級别.例如:long long int 的級别高于int, int的級别高于char等.在表達式中,其級别低于int或unsigned int的任何整數類型均可被替換成int或unsigned int類型.

上一篇: c99
下一篇: C99之_Complex

繼續閱讀