C語言的發展歷史大致上分為4個階段:Old Style C、C89、C99和C11.
C89是最早的C語言規范,於1989年提出,1990年先由ANSI(美國國家標准委員會,American National Standards Institute)推出ANSI版本,後來被接納為ISO國際標准(ISO/IEC9899:1990),因而有時也稱為C90,最經典的C語言教材[K&R]就是基於這個版本的,C89是目前最廣泛采用的C語言標准,大多數編譯器都完全支持C89,C99(ISO/IEC9899:1999)是在1999年推出的,加入了許多新的特性,但目前仍沒有得到廣泛支持,在C99推出之後相當長的一段時間裡,連gcc也沒有完全實現C99的所有特性。2011年12月8號,ISO 發布了新的 C 語言的新標准——C11,之前被稱為C1X,官方名稱 ISO/IEC 9899:2011。
本文地址:http://www.cnblogs.com/archimedes/p/c99-new-feature.html,轉載請注明源地址。
現在介紹一下C99相對於C89或者ANSI C的新特性:
complex.h
是C標准函數庫中的頭文件,提供了復數算術所需要的宏定義與函數聲明。
#define complex _Complex #define _Complex_I ((const float _Complex)__I__) #define I _Complex_I
C99規定了關鍵字_Complex
。因而有3種復數類型:
double _Complex
float _Complex
long double _Complex
次序不是必須遵守的,比如float _Complex也可以寫成_Complex float。_Complex_I
擴展為類型為const float _Complex
的常量值,其值為虛數單位。C99規定complex
作為宏擴展為_Complex
。但C++未定義complex
宏。gcc僅支持complex type,不支持imaginary type。因此宏I
擴展為_Complex_I
。
<complex.h>裡面還包含了不少支持復數的數學函數(c打頭的就是):
1、ccos,csin,ctan,cacos,casin,catan:復數域內的三角函數,有對應的f和l版本。
2、ccosh,csinh,ctanh,cacosh,casinh,catanh:復數域內的雙曲函數,有對應的f和l版本。
3、cexp,clog,cabs,cpow,csqrt:復數域內的指數、對數、絕對值、冪函數,有對應的f和l版本。
4、carg,cimag,creal,conj,cproj:獲取象限角、虛數部分、實數部分、a=x及b=-y、Riemann球上的投影,有對應的f和l版本。
代碼:
#include<stdio.h> #include<complex.h> int main() { double complex cmp = 1.3 + 2.3*I; printf("%f + %fi\n", creal(cmp), cimag(cmp)); return 0; }
在初始化結構體和數組時,可以通過指定具體成員名或數組下標來賦初值
要指定數組的索引對應的值,可以在相應的元素值前使用‘[index] =’,index必須是常量表達式例如:
int a[6] = { [4] = 29, [2] = 15 };
等價於:
int a[6] = { 0, 0, 15, 0, 29, 0 };
還可以向下面這樣初始化:
int a[10] = { [1] = 1, [8 ... 9] = 10 };
這樣可以只初始化a[1], a[8], a[9]三個元素,其他元素的值為0,等價於:
int a[10] = {0, 1, 0, 0, 0, 0, 0, 0, 10, 10};
對於結構體,指定成員名初始化可以使用‘.fieldname=’,例如:
struct point { int x, y; };
接下來初始化:
struct point p = { .y = yvalue, .x = xvalue }; // 等價於 struct point p = { xvalue, yvalue };
還可以使用冒號:
struct point p = { y: yvalue, x: xvalue };
當然也可以用在union中:
union foo { int i; double d; }; union foo f = { .d = 4 };
C99允許可以定義一個長度為變量的數組(這個數組的長度可以到運行時才決定)
FILE * concat_fopen (char *s1, char *s2, char *mode) { char str[strlen (s1) + strlen (s2) + 1]; strcpy (str, s1); strcat (str, s2); return fopen (str, mode); } GNU示例代碼也可以在結構體或是聯合中使用VLA:
void foo (int n) { struct S { int x[n]; }; }
你可以使用alloca函數實現類似的功能,但是alloca函數並不是都實現,從另一角度而言,VLA更加的優秀
也可以使用VLA作函數參數:
struct entry tester (int len, char data[len][len]) { /* ... */ }
當然也可以後傳len
struct entry tester (int len; char data[len][len], int len) //注意分號 { /* ... */ }
示例代碼:
#include<stdio.h> void func(int n) { int vla[n]; printf("%d\n", sizeof(vla)); } int main() { func(4); return 0; }
gcc支持像C++風格的注釋,以‘//’開頭直到一行的結束,很多其他支持C99的C編譯器都支持,但是c99之前的版本有可能不支持
參見《C語言柔性數組》一文
C99支持64位整型,使用long long int 或使用unsigned long long int,將整型常量聲明為long long int,在整數的後面加上‘LL’,若為unsigned long long int,則加上‘ULL’
c/c++中的inline,使用在函數聲明處,表示程序員請求編譯器在此函數的被調用處將此函數實現插入,而不是像普通函數那樣生成調用代碼(申請是否有效取決於編譯器)。一般地說,這樣作的優點是省掉了調用函數的開銷;缺點則是可能會增加代所生成目標代碼的尺寸
實際上,即使沒有手工指定inline函數,編譯器一般還會選擇一些代碼量較小但使用頻繁的函數作為inline函數,以此作為性能優化的途徑之一。
和帶參宏定義(Parameterized Macro)相比,具備以下優點:
示例代碼:
static inline int inc (int *a) { return (*a)++; }
記得以前都是自己寫#define TRUE 1, #define FALSE 0 或者 enum boolean之類的宏,現在可以使用<stdbool.h>的bool類型啦
簡單來說復合常量就是允許你定義一個匿名的結構體或數組變量。如:
struct foo {int a; char b[2];} structure; structure = ((struct foo) {x + y, 'a', 0});
等價於:
{ struct foo temp = {x + y, 'a', 0}; structure = temp; }
也可以創建一個數組:
char **foo = (char *[]) { "x", "y", "z" };
更多實例:
static struct foo x = (struct foo) {1, 'a', 'b'}; static int y[] = (int []) {1, 2, 3}; static int z[] = (int [3]) {1}; //等價於下面的代碼: static struct foo x = {1, 'a', 'b'}; static int y[] = {1, 2, 3}; static int z[] = {1, 0, 0};
C99引入了C++中的for循環變量初始化方式:
for(int i = 0; i < 10; ++i) { ...; }
除了寫起來方便以外,循環變量的生存周期也被最小化了。這也順便杜絕了那種把循環變量帶到循環外頭繼續用的惡習
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年第一次修訂時引進,用於支持多字節和寬字節分類函數
注意:還有一些新特性未總結進來,待充分理解實踐之後將陸續補充
https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions