C語言

維基百科,自由的百科全書
(重定向自C99
跳轉到: 導覽搜尋
C語言
The C Programming Language logo.svg
編程範型 程序式
面市時間 1972年
設計者 丹尼斯·里奇(Dennis Ritchie)
實作者 丹尼斯·里奇(Dennis Ritchie)和肯·湯普遜(Ken Thompson)
最近釋出日期 ISO/IEC 9899 2011 / 2011年11月
主要實作產品 ClangGCCMSVCTurbo CWatcom C
啟發語言 B語言組合語言
影響語言 awk, BitC, csh, C++, C#, Concurrent C, D, Java, JavaScript, Objective-C, Perl, PHP
作業系統 跨平台

C語言,是一種通用的、程序式的程式語言,廣泛用於系統應用軟體的開發。具有高效、靈活、功能豐富、表達力強和較高的可移植性等特點,在程式設計師中備受青睞。最近25年是使用最為廣泛的程式語言[1]

C語言是由丹尼斯·里奇於1969年至1973年以B語言為基礎,在貝爾實驗室開發完成。目前,C語言編譯器普遍存在於各種不同的作業系統中,例如UNIXMS-DOSMicrosoft WindowsLinux等。C語言的設計影響了許多後來的程式語言,例如C++Objective-CJavaC#等。

二十世紀八十年代,為了避免各開發廠商用的C語言語法產生差異,由美國國家標準局為C語言訂定了一套完整的國際標準語法,稱為ANSI C,作為C語言的標準。二十世紀八十年代至今的有關程式開發工具,一般都支援符合ANSI C的語法。

設計哲學[編輯]

C語言是一個程式語言,設計目標是提供一種能以簡易的方式編譯、處理低階記憶體、產生少量的機器碼以及不需要任何執行環境支援便能執行的程式語言。C語言也很適合搭配組合語言來使用。儘管C語言提供了許多低階處理的功能,但仍然保持著良好跨平台的特性,以一個標準規格寫出的C語言程式可在許多電腦平台上進行編譯,甚至包含一些嵌入式處理器(微控制器或稱MCU)以及超級電腦等作業平台。

特色[編輯]

  • C語言是一個有結構化程式設計、具有變數作用域(variable scope)以及遞迴功能的程序式語言。
  • C語言傳遞參數均是以值傳遞(pass by value)[2],另外也可以傳遞指標(a pointer passed by value)。
  • 不同的變數類型可以用結構體(struct)組合在一起。
  • 只有32個保留字(reserved keywords),使變數、函式命名有更多彈性。
  • 部份的變數類型可以轉換,例如整型和字元型變數。
  • 透過指標(pointer),C語言可以容易的對記憶體進行低階控制。
  • 編譯預處理(preprocessor)讓C語言的編譯更具有彈性。

歷史[編輯]

早期發展[編輯]

肯·湯普遜和丹尼斯·里奇, 是C程式語言的開發人.

C語言最早是由丹尼斯·里奇為了在PDP-11電腦上運行的UNIX系統所設計出來的程式語言,第一次發展在1969年到1973年之間。之所以被稱為「C」是因為C語言的很多特性是由一種更早的被稱為B語言的程式語言中發展而來。早期作業系統的核心大多由組合語言組成,隨著C語言的發展,C語言已經可以用來編寫作業系統的核心。1973年,Unix作業系統核心正式用C語言改寫,這是C語言第一次應用在作業系統的核心編寫上。

K&R C[編輯]

1978年,丹尼斯·里奇(Dennis Ritchie)和布萊恩·柯林漢合作出版了《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 函式
  • 函式返回 structunion 型別
  • void * 資料型別

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

傳統C語言到ANSI/ISO標準C語言的改進包括:

  • 增加了真正的標準庫
  • 新的預處理命令與特性
  • 函式原型允許在函式申明中指定參數型別
  • 一些新的關鍵字,包括 constvolatilesigned
  • 寬字元、寬字串與多位元組字元
  • 對約定規則、宣告和型別檢查的許多小改動與澄清

WG14工作小組之後又於1994年,對1985年頒布的標準做了兩處技術修訂(缺陷修復)和一個補充(擴充功能)。下面是 1994 年做出的所有修改:

  • 3 個新的標準庫標頭檔 iso646.h、wctype.h 和 wchar.h
  • 幾個新的記號與預定義巨集,用於對國際化提供更好的支援
  • printf/sprintf 函式一系列新的格式代碼
  • 大量的函式和一些型別常量,用於多位元組字元寬位元組字元

C99[編輯]

在ANSI的標準確立後,C語言的規範在一段時間內沒有大的變動,然而C++在自己的標準化建立過程中繼續發展壯大。《標準修正案一》在1994年為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] 的形式。不過考慮到效率和實作,不定長陣列不能用在全域,或 structunion 里。
  • 變數宣告不必放在語句塊的開頭,for 語句提倡寫成 for(int i=0;i<100;++i) 的形式,即i 只在 for 語句塊內部有效。
  • 允許採用(type_name){xx,xx,xx} 類似於 C++ 的建構函式的形式構造匿名的結構體。
  • 初始化結構的時候允許對特定的元素賦值,形式為:
    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 賦值的
  • 格式化字串中,利用 \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 定義的最後一個陣列不指定其長度,寫做 [](flexible array member)。
  • 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 用於複製 ... 的參數。

進一步了解[編輯]

C語言由函式和變數組成,C的函式就像是Fortran中的子程式和函式。

在C語言中,程式從 main 開始執行。main 函式透過呼叫和控制其他函式進行工作。例如上面的printf。程式設計師可以自己寫函式,或從庫中呼叫函式。在上面的return 0; 使得 main 返回一個值給呼叫程式的殼層,表明程式是否成功執行。

一個C語言的函式由返回值、函式名、參數列和函式體組成。函式體的語法和其它的複合的語句部分是一樣的。

複合語句[編輯]

C語言中的複合語句(或稱語句塊)的格式為:

{
    語句;
    語句;
    /* ... */
}

複合語句可以使得幾個語句從文法上變成一個語句。

有時必須使用複合語句,否則會產生錯誤。例如,在運用迴圈語句的時候,如果迴圈體(即迴圈中執行部分)包含多個語句(以分號隔開),則必須使用花括弧將他們合併成一個複合語句。如果不這麼做,系統僅把第一個分號前的內容看做迴圈體。

需要注意的是,部分C編譯器並不支援在任意位置使用複合語句。

條件語句[編輯]

C語言有三種條件語句形式。兩種是if,另一種是switch

兩種if包括:

if(運算式)
    語句;

以及

if(運算式)
    語句;
else
    語句;

運算式的值非零表示條件為真;如果條件為假,程式將跳過if處的語句,直接執行if後面的語句。但是如果if後面有else,則當條件為假時,程式跳到else處執行。ifelse後面的語句可以是另個if語句,這種套疊式的結構,允許更複雜的邏輯控制流程得以實現。在一般情況下,else一定與最接近的if成對,必要時可用括弧{}越過此限制。比較下面兩種情況:

if(運算式)
    if (運算式)
        語句;
    else
        語句;
if(運算式)
{
    if(運算式)
        語句;
}
else
    語句;

switch通常用於對幾種有明確值的條件進行控制。它要求的條件值通常是整數或字元。與switch搭配的條件轉移是case。使用case後面的標值,控制程式將跳到滿足條件的case處一直往下執行,直到語句結束或遇到break。通常可以使用default把其他例外的情況包含進去。如果switch語句中的條件不成立,控制程式將跳到default處執行;如果省略default子句,則直接執行下一語句。switch是可以巢狀的。

switch(運算式)
{
    case1:
        語句;
        break;
    case2:
        語句;
        break;
    default:
        語句;
}

循環語句(迴圈)[編輯]

C語言有三種形式的循環語句:

do
    語句
while(表達式);

while(表達式)
    語句;

for(表達式1; 表達式2; 表達式3)
    語句;

whiledo中,語句將執行到表達式的值為零時結束。在do...while語句中,循環將至少被執行一次。這三種循環結構可以互相轉化:

for (<表達式1>; <表達式2>; <表達式3>)
     <語句>;

如果<語句>中不使用continue語句的話,相當於

<表達式1>;
while (<表達式2>) {
    <語句>;
    <表達式3>;
}

當循環條件一直為真時,將產生無窮迴圈。

跳轉語句[編輯]

跳轉語句包括四種:goto,continue,break和return

goto語句是無條件轉移語句:

goto 標記;

標記必須在當前函式中定義,使用「標記:」的格式定義。程式將跳到標記處繼續執行。由於goto容易產生閱讀上的困難,所以應該儘量少用。

continue語句用在迴圈語句中,作用是結束當前一輪的迴圈,馬上開始下一輪迴圈。

break語句用在迴圈語句或switch中,作用是結束當前迴圈,跳到循環體外繼續執行。但是使用break只能跳出一層迴圈。在要跳出多重迴圈時,可以使用goto使得程式更為簡潔。

當一個函式執行結束後要返回一個值時,使用returnreturn可以跟一個運算式或變數。如果return後面沒有值,將執行不返回值。

在C語言中的運算子號[編輯]

()、 []、 -> 、 .、 !、 ++、 --   圓括弧、方括弧、指標、成員、邏輯非、自加、自減
++ 、 -- 、 * 、 & 、 ~ 、 ! 、 + 、 - 、 sizeof、(cast)  單目運算子
* 、 / 、 % 算術運算子
+ 、 -  算術運算子
<< 、 >> 位運算子
< 、 <= 、 > 、 >= 關聯運算子
== 、 != 關聯運算子號
& 位與
^ 位異或
| 位或
&& 邏輯與
|| 邏輯或
 ? 、 : 條件運算子
= 、 += 、 -= 、 *= 、 /= 、 %= 、 &= 、 |= 、 ^= 設定運算子
, 順序運算子

比較特別的是,位元右移(>>)運算子可以是算術(左端補最高有效位)或是邏輯(左端補 0)位移。例如,將 11100011 右移 3 位元,算術右移後成為 11111100,邏輯右移則為 00011100。因算術位元右移較適於處理帶負號整數,所以幾乎所有的編譯器都是算術位元右移。[4]

運算子的優先順序從高到低大致是:單目運算子、算術運算子、關聯運算子、邏輯運算子、條件運算子、設定運算子(=)和逗號運算子。

資料型別[編輯]

基礎資料型別[編輯]

注意:以下是典型的資料位長和範圍。但是編譯器可能使用不同的資料位長和範圍。這取決於使用的編譯器。請參考具體的參考手冊。

在標頭檔<limits.h>和<float.h>中說明了基礎資料的長度。float,double和long double的範圍就是在IEEE 754標準中提及的典型資料。

關鍵字 位長(位元組) 範圍 格式化字串
char 1 -128..127(或0..255,與體系結構相關)  %c
unsigned char 1 0..255  %c, %hhu
signed char 1 -128..127  %c, %hhd, %hhi
int 2(16位元系統) 或
4
-32768..32767 或
-2147483648..2147483647
 %i, %d
unsigned int 2 或
4
0..65535 或
0..4294967295
 %u
signed int 2 或
4
-32768..32767 或
-2147483648..2147483647
 %i, %d
short int 2 -32768..32767  %hi, %hd
unsigned short 2 0..65535  %hu
signed short 2 -32768..32767  %hi, %hd
long int 4 或
8[5]
-2147483648..2147483647 或
-9223372036854775808..9223372036854775807
 %li, %ld
unsigned long 4 或
8
0..4294967295 或
0..18446744073709551615
 %lu
signed long 4 或
8
-2147483648..2147483647 或
-9223372036854775808..9223372036854775807
 %li, %ld
long long 8 -9223372036854775808..9223372036854775807  %lli, %lld
unsigned long long 8 0..18446744073709551615  %llu
float 4 3.4x10−38..3.4x10+38 (7 sf)  %f, %e, %g
double 8 1.7x10−308..1.7x10+308 (15 sf)  %lf, %e, %g
long double 8 或以上 編譯器相關  %Lf, %Le, %Lg

結構資料型別[編輯]

結構資料型別允許構造由多個基礎資料型別組合而成的複雜結構,結構資料型別為物件導向的藍本。以下的結構資料型別透過指標實作了二元樹結構:

struct binarytree {
  int data;
  struct binarytree *lchild; // left child of the node
  struct binarytree *rchild; // right child of the node
}

為結構資料型別定義變數時通常會用到動態記憶體分配:

struct binarytree *tree;
tree = (struct binarytree *)malloc(sizeof(struct binarytree)); // 分配該結構所需的記憶體單元數量到tree指標
tree->data = 1;
tree->lchild = (struct binarytree *)malloc(sizeof(struct binarytree));
...

由於C語言不具備自動垃圾收集(Garbage Collection)功能,使用完畢後需要呼叫free()來釋放之前透過malloc分配的記憶體。詳見以下指標章節。

陣列[編輯]

如果一個變數名後面跟著一個有數字的中括弧,這個聲明就是陣列聲明。字串也是一種陣列,它們以ASCII的NUL作為陣列的結束。要特別注意的是,方括內的索引值是從0算起的。

例如:

int myvector [100]/* 從myvector[0]至myvector[99]止共100個元素 */
char mystring [80]
float mymatrix [3] [2] = {2.0 , 10.0, 20.0, 123.0, 1.0, 1.0};
int notfull [3][3] = {{1},{1,2,3},{4,5}};               (*)
char lexicon  [10000] [300]/* 共一萬個最大長度為300的字元陣列。*/
int a[3][4]

上面最後一個例子創建了一個陣列,但也可以把它看成是一個多維陣列。注意陣列的下標從0開始。這個陣列的結構如下:

a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]

例子中notfull創建了一個3*3的二維陣列,初始化時有些元素並未賦值。如下:

1 0 0
1 2 3
4 5 0

為0的位置的數值是隨機的,但通常會被補上0。

指標[編輯]

如果一個變數宣告時在前面使用 * 號,表明這是個指標型變數。換句話說,該變數儲存一個位址,而 *(此處特指單目運算子 * ,下同。C語言中另有 雙目運算子 * ) 則是取內容操作符,意思是取這個記憶體位址里儲存的內容。指標是 C 語言區別於其他同時代高階語言的主要特徵之一。

指標不僅可以是變數的位址,還可以是陣列、陣列元素、函式的位址。透過指標作為形式參數可以在函式的呼叫過程得到一個以上的返回值(不同於return(z)這樣的僅能得到一個返回值。

指標是一把雙刃劍,許多操作可以透過指標自然的表達,但是不正確的或者過分的使用指標又會給程式帶來大量潛在的錯誤。

例如:

int * pi;     /* 指向整型資料的指標變數 */
int * api[3];/* 由指向整型資料的指標構成的陣列,長度為 3 */
char ** argv; /* 指向一個字元指標的指標 */
struct
{
    int member;
} stinst, * pst = & stinst;       /* pst是一個指向一個匿名結構體的指標 */

儲存在指標中的位址所指向的數值在程式中可以由 * 讀取。例如,在第一個例子中, *pi 是一個整型資料。這叫做參照一個指標。

另一個運算子 &,叫做取位址運算子,它將返回一個變數、陣列或函式的儲存位址。因此,下面的例子:

int i, *pi; /* int and pointer to int */
pi = &i;

i*pi 在程式中可以相互替換使用,直到 pi 被改變成指向另一個變數的位址。

當指標指向結構體時,可以使用運算子 -> 代替 *和. 的作用,如以下兩個運算式為等效:

(*pst).member
pst->member

字串[編輯]

C語言的字串其實就是char型陣列,所以使用字串並不需要參照庫。但是C標準庫確實包含了一些用於對字串進行操作的函式,使得它們看起來就像字串而不是陣列。使用這些函式需要參照標頭檔<string.h>


檔案輸入/輸出[編輯]

在C語言中,輸入和輸出是經由標準函式庫中的一組函式來實現的。在ANSI/ISO C中,這些函式被定義在標頭檔<stdio.h>中。

標準輸入/輸出[編輯]

有三個標準輸入/輸出是標準I/O庫預先定義的:

  • stdin 標準輸入
  • stdout 標準輸出
  • stderr 輸入輸出錯誤


下面的這個例子顯示了一個過濾程式(filter program)是怎樣構成的。

# include <stdio.h>

int main(int argc, const char * argv[])
{
    int c;
    while (1)
    {
        c = getchar();
        if (c==EOF)
        {
            perror("getchar()");
            return -1;
        }
        putchar(c);
    }

    return 0;
}

函式[編輯]

C語言的基本結構單位是函式。系統首先呼叫 main函式(主函式),透過函式的巢狀呼叫,再呼叫其他函式。函式可以是系統內建的函式,也可以是使用者定義的函式。C語言中,不允許函式的巢狀定義。

記憶體管理[編輯]

C語言的特色之一是:程式設計師必須親自處理記憶體的分配細節。

C語言使用棧(Stack)來保存函式返回位址/棧禎基址、完成函式的參數傳遞和函式局部變數的儲存。 如果程式需要在執行的過程中動態分配記憶體,可以利用(Heap)來實作。

基本上C程式的元素儲存在記憶體的時候有3種分配策略:

  • 靜態分配

如果一個變數宣告為全域變數或者是函式的靜態變數,這個變數的儲存將使用靜態分配方式。靜態分配的記憶體一般會被編譯器放在資料段代碼段來儲存,具體取決於實作。這樣做的前提是,在編譯時就必須確定變數的大小。 以IA32的x86平台及gcc編譯器為例,全域及靜態變數放在資料段的低端;全域及靜態常量放在代碼段的進階。

  • 自動分配

函式的自動局部變數應該隨著函式的返回會自動釋放(失效),這個要求在一般的體系中都是利用堆疊(Stack)來滿足的。相比於靜態分配,這時候,就不必絕對要求這個變數在編譯時就必須確定變數的大小,執行時才決定也不遲,但是C89仍然要求在編譯時就要確定,而C99放鬆了這個限制。但無論是C89還是C99,都不允許一個已經分配的自動變數執行時改變大小。

所以說C函式永遠不應該返回一個局部變數的位址

要指出的是,自動分配也屬於動態分配,甚至可以用alloca函式來像分配堆(Heap)一樣進行分配,而且釋放是自動的。

  • 動態分配

還有一種更加特殊的情況,變數的大小在執行時有可能改變,或者雖然單個變數大小不變,變數的數目卻有很大彈性,不能靜態分配或者自動分配,這時候可以使用(Heap)來滿足要求。ANSI C定義的堆操作函式是malloc、calloc、realloc和free。

使用(Heap)記憶體將帶來額外的開銷和風險。

安全問題[編輯]

C語言的特色之一是:語言不負責記憶體邊界檢查。最重要的是指標操作

[編輯]

C語言的標準文件要求了一個平台移植C語言的時候至少要實作的一些功能和封裝的集合,稱為「標準庫」,標準庫的宣告頭部通過前置處理器命令#include進行參照。

在C89標準中:

檔案 簡介說明
<assert.h> 斷言相關
<ctype.h> 字元型別判斷
<errno.h> 標準報錯機制
<float.h> 浮點運算
<limits.h> 各種體系結構限制
<locale.h> 在地化介面
<math.h> 數學函式
<setjmp.h> 跨函式跳轉
<signal.h> 訊號(類似UNIX訊號定義,但是差很遠)
<stdarg.h> 可變參處理
<stddef.h> 一些標準巨集定義
<stdio.h> 標準I/O庫
<stdlib.h> 標準工具庫函式
<string.h> ASCIIZ字串及任意記憶體處理常式
<time.h> 時間相關

在94年的修正版中

  • <iso646.h>
  • <wchar.h>
  • <wctype.h>

在C99中增加了六個函式庫

  • <complex.h>
  • <fenv.h>
  • <inttypes.h>
  • <stdbool.h>
  • <stdint.h>
  • <tgmath.h>

以上是C語言的標準,而各個平台各自又對C庫函式進行的各種擴充,就浩如煙海了。如POSIX CGNU C等。

工具軟體[編輯]

工具軟體可以幫助程式設計者避免一些程式中潛藏或容易出現的問題,例如常會造成程式未預期動作或是執行期錯誤的程式碼。

許多語言都有自動源代碼檢查及審計工具,C語言也有類似工具,像是Lint。可以在程式剛寫好時用Lint找出可能有問題的程式,通過Lint後再用C編譯器進行編譯,許多編譯器也可以設定是否要針對一些可能有問題的程式碼提出警告。MISRA C是一套針對嵌入式系統的法則,可主要也是避免一些可能有問題的程式碼。

也有一些編譯器、程式庫或作業系統可以處理一些非標準C語言的功能,例如邊界值檢查、緩衝區溢位偵測、序列化自動垃圾回收功能。

使用像ValgrindIBM Rational Purify英語Purify等軟體工具,或者連結有特別malloc函式的程式庫,有助於找出一些運行期記憶體使用的問題。

保留關鍵字[編輯]

char short int unsigned
long float double struct
union void enum signed
const volatile typedef auto
register static extern break
case continue default do
else for goto if
return switch while

C99新增關鍵字[編輯]

_Bool _Complex _Imaginary inline restrict

C11新增關鍵字[編輯]

_Alignas _Alignof _Atomic _Generic _Noreturn
_Static_assert _Thread_local

[6]

經典錯誤[編輯]

void main的用法並不是任何標准制定的[7] [8],是Microsoft制定的。 C語言正確的語法是int main[9]。 在 C++ 標準中,雖然 main 的標準型態應是 int,但編譯器實作中也可以自行定義型態,不過,所有實作均應接受 int main 的用法[10]

C//[編輯]

C// 是一種結構化的並列語言,讀作C parallel。它基於標準C語言但擴充功能了為數不多的構造用來表示並列性和行程互動。C// 的核心是稱為一致區域的構造,它方便了結構化的、確定的、終止的和複合的並列程式的開發。[來源請求]

參考文獻[編輯]

  1. ^ TIOBE Programming Community Index [TIOBE編程社群指數]. 2012 [2012-11-03] (英文). 
  2. ^ Brian W. Kernighan and Dennis M. Ritchie. The C programming Language. Prentice-Hall. 1988. ISBN 0-13-110362-8 (英文). "In C, all function arguments are passed ``by value." 
  3. ^ GCC從3.0版本開始正式支援C99(-std=c99)
  4. ^ 經測試,gcc4.4.3使用C99標準的結果依然是00011100,即邏輯移位。
  5. ^ GCC、Clang 等實作中,64位元代碼的long型別為64位元,而MSVC中則維持32位元
  6. ^ ISO/IEC 9899:201x (ISO C11) Committee Draft
  7. ^ Bjarne Stroustrup's C++ Style and Technique FAQ (Modified October 4, 2009) - Can I write "void main()"?
  8. ^ 用 C99 進行開放原始碼的開發
  9. ^ ISO/IEC 9899-1999, Section 5.1.2.2.1 Program startup
  10. ^ 「It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following definitions of main: ...(下略)」,引自 ISO/IEC 14882, 第一版(1998)與第二版(2003), section 3.6.1 Main function

外部連結[編輯]

參見[編輯]