C語言原來是沒有統一的標准的,第一個標准是90左右確定的,內容較以前有些改進:
1、增加了真正的標准庫;
2、新的預處理命令與特性;
3、函數原型允許在函數申明中;
4、指定參數類型一些新的關鍵字,包括 const、volatile 與 signed;
5、寬字符、寬字符串與多字節字符;
6、對約定規則、聲明和類型檢查的許多小改動與澄清;
后來到了99年就有了新的修正:
1、增加了對編譯器的限制,比如源程序每行要求至少支持到 4095 字節,變量名函數名的要求支持到 63 字節(extern 要求支持到 31);
2、增強了預處理功能。例如:宏支持取可變參數 #define Macro(...) __VA_ARGS__;
使用宏的時候,允許省略參數,被省略的參數會被擴展成空串;
支持 // 開頭的單行注釋(這個特性實際上在C89的很多編譯器上已經被支持了);
3、增加了新關鍵字 restrict, inline, _Complex, _Imaginary, _Bool;支持 long long, long double _Complex, float _Complex 等類型;
4、支持不定長的數組,即數組長度可以在運行時決定,比如利用變量作為數組長度。聲明時使用 int a[var] 的形式。不過考慮到效率和實現,不定長數組不能用在全局,或struct 與union 里。
5、變量聲名不必放在語句塊的開頭,,for 語句提倡寫成 for(int i=0;i<100;++i) 的形式,即i 只在for 語句塊內部有效。
6、允許采用(type_name){xx,xx,xx} 類似於 C++ 的構造函數的形式構造匿名的結構體。
7、初始化結構的時候允許對特定的元素賦值,形式為:
struct test{int a[3],b;} foo[] = { [0].a = {1}, [1].a = 2 }
struct test{int a, b, c, d;} foo= { .a=1, .c=3,4, .b=5 }; // 3,4 是對 .c,.d 賦值的
8、格式化字符串中,利用 \u 支持 unicode 的字符。
9、支持 16 進制的浮點數的描述;printf scanf 的格式化串增加了對 long long int 類型的支持;浮點數的內部數據描述支持了新標准,可以使用 #pragma 編譯器指令指定。
10、除了已有的 __line__ __file__ 以外,增加了 __func__ 得到當前的函數名。
11、允許編譯器化簡非常數的表達式;取消了函數返回類型默認為 int 的規定。
12、修改了 / % 處理負數時的定義,這樣可以給出明確的結果,例如在C89中-22 / 7 = -3, -22 % 7 = -1,也可以-22 / 7= 4, -22 % 7 = 6。 而C99中明確為-22 / 7 = -3, -22 % 7 = -1,只有一種結果。
13、允許 struct 定義的最后一個數組不指定其長度,寫做 [](flexible array member)。
14、const const int i 將被當作const int i 處理;輸入輸出對寬字符以及長整數等做了相應的支持。
15、增加和修改了一些標准頭文件,比如定義 bool 的 <stdbool.h> ,定義一些標准長度的 int 的 <inttypes.h> ,定義復數的 <complex.h> ,定義寬字符的 <wctype.h> ,類似於泛型的數學函數 <tgmath.h>, 浮點數相關的 <fenv.h>。 在<stdarg.h> 增加了 va_copy 用於復制 ... 的參數。 里增加了 struct tmx ,對 struct tm 做了擴展。
在11年的時候ISO正式發布了新的C語言的新標准C11:
1、對齊處理(Alignment)的標准化(包括_Alignas標志符,alignof運算符, aligned_alloc函數以及<stdalign.h>頭文件。
2、_Noreturn 函數標記,類似於 gcc 的 __attribute__((noreturn))。
3、_Generic 關鍵字。
4、多線程(Multithreading)支持,包括:
_Thread_local存儲類型標識符,<threads.h>頭文件,里面包含了線程的創建和管理函數。
_Atomic類型修飾符和<stdatomic.h>頭文件。
5、增強的Unicode的支持。基於C Unicode技術報告ISO/IEC TR 19769:2004,增強了對Unicode的支持。包括為UTF-16/UTF-32編碼增加了char16_t和char32_t數據類型,提供了包含unicode字符串轉換函數的頭文件<uchar.h>.
6、刪除了 gets() 函數,使用一個新的更安全的函數gets_s()替代。
7、增加了邊界檢查函數接口,定義了新的安全的函數,例如 fopen_s(),strcat_s()
8、匿名結構體/聯合體支持。這個在gcc早已存在,C11將其引入標准。
9、靜態斷言(Static assertions),_Static_assert(),在解釋 #if 和 #error 之后被處理。
10、新的 fopen() 模式,(“…x”)。類似 POSIX 中的 O_CREAT|O_EXCL,在文件鎖中比較常用。
11、新增 quick_exit() 函數作為第三種終止程序的方式。當 exit()失敗時可以做最少的清理工作。
C90和C99容易弄混,這也是現在用的最多的兩個版本,至於C11的話基本沒見人用,反正有了也總結一下 。
C99標准現在還有些編譯器支持的不太好,但是用gcc已經完全沒問題了。
C99重要的更新如下:
指定初始化(Designated Initializers)
允許對數組元素或結構體元素的特定成員進行初始化而不用按順序進行初始化。 主要是結構體成員的指定,和數組成員的指定。
結構體成員,比如,
struct S { int a; int b; }; struct S instance1={ .a=1, }; struct S array1[5]={ [1].a = 3, [1].b = 5, { // array1[2] = {7, 11} .a = 7, .b = 11 } // array1[4] = {13, 17} [4] = { .a = 13, .b = 17 } };
變長數組(Variable Length Arrays)
C99支持動態長度的數組(VLA),也就是數組在棧上由運行時分配。退出作用域時,數組使用的空間被釋放。所以VLA不能在全局定義,或者有extern,static修飾符。
int n; //define a variable n int array[n]; //define an array with length n
伸縮型數組成員(Flexible Array Members)
C99支持伸縮數組成員,最后一個結構體成員的大小可以在運行時分配。
struct flex_array { int a; double b; char c[]; }; struct flex_array *fa_sample = (struct flex_array*)malloc(sizeof(flex_array)+100*sizeof(char)); fa_sample->c[2] = 's';
bool類型
用<stdbool.h>來使用bool類型,而使用true或者false來為變量賦值或比較。
long long類型
新的long long類型為了統一不同編譯器實現對64位的支持,在format時使用%lld來輸出long long。
inline函數
盡量使用inline函數來替代所謂的“函數宏”。
混合聲明(mix declarations and code)
現在可以在代碼里隨處定義變量了。但是要注意作用域。
// 行注釋
不解釋,編譯器早就支持了。
for循環變量初始化(for loop intializers)
在for語句里可以定義局部變量了,早就該有的特性。
變參宏(Variadic Macros)
gcc的編譯器很早之前就支持這個特性了,微軟的編譯器之前是不可以這個用的。最新的版本不確定。
#define debug(fmt, ...) \ printf("[DEBUG] %s:%d <%s>: " fmt, \ __FILE__, __LINE__, __func__, ##__VA_ARGS__)
復合常量(Compound Literals)
復數(Complex Numbers)
用<complex.h>來使用complex類型
restrict指針
reference
https://blog.csdn.net/syrchina/article/details/6662243
C11 新特性
C11的主要新特性是增加了<thread.h>,還有thread_local修飾符表示變量只在本線程可用。另外相比<pthread.h>,調用格式完全類似,只是函數名前綴縮短了一下,現在是thrd_,mtx_, cnd_和tss_作為前綴。
