C语言

設計

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

早期發展

C語言最早由丹尼斯·里奇（Dennis Ritchie）為了在PDP-11電腦上運行的Unix系統所設計出來的程式語言，第一次發展在1969年到1973年之間。
C源於BCPL語言，後者由馬丁·理察德（Martin Richards）於1967年左右設計實現。BCPL是一門"無類型"的程式語言：它僅能操作一種資料類型，即機器字（machine word）。1970年，肯·湯普遜為執行在PDP-7上的首個Unix系統設計了一個精簡版的BCPL，這個語言被稱為B語言，它也是無類型的。
Unix最早運行在PDP-7上，是以組合語言寫成。在PDP-11出現後，丹尼斯·里奇與肯·湯普遜著手將Unix移植到PDP-11上，無類型的語言在PDP-11上愈發顯得合適。PDP-11提供了多種不同規格大小的基本物件：一位元組長的字元，兩位元組長的整型數以及四位元組長的浮點數。B語言無法處理這些不同規格大小的物件，也沒有提供單獨的運算子去操作它們。
C語言最初嘗試通過向B語言中增加資料類型的想法來處理那些不同類型的資料。和大多數語言一樣，在C中，每個物件都有一個類型以及一個值；類型決定了可用於值的操作的含義，以及物件占用的儲存空間大小。
1973年，Unix作業系統的核心正式用C語言改寫，這是C語言第一次應用在作業系統的核心編寫上。
1975年C語言開始移植到其他機器上使用。史蒂芬·強生實現了一套「可移植編譯器」，這套編譯器修改起來相對容易，並且可以為不同的機器生成程式碼。從那時起，C在大多數計算機上被使用，從最小的微型計算機到與CRAY-2超級計算機。C語言很規範，即使沒有一份正式的標準，你也可以寫出C程式，這些程式無須修改就可以執行在任何支援C語言和最小執行時環境的計算機上。
C最初在小型機器上實現，並且繼承了一系列小語種程式語言的特點；與功能相比，C的設計者更傾向於簡單和優雅。此外，從一開始，C語言就是為系統級編程而設計，程式的執行效率至關重要，因此，C語言與真實機器能力的良好匹配也就不足為奇。例如，C語言為典型硬體所直接支援的物件：字元，整數（也許有多種大小），以及浮點數（同樣可能有多種大小）提供了相應的基本資料類型。

C11

2011年12月8日，ISO正式發布了新的C語言的新標準C11，之前被稱為C1X，官方名稱為ISO/IEC 9899:2011。新的標準提高了對C++的相容性，並增加了一些新的特性。這些新特性包括泛型巨集、多執行緒、帶邊界檢查的函式、匿名結構等。

C18

C18沒有引入新的語言特性，只對C11進行了補充和修正。

Hello World 程式

下面是一個在標準輸出裝置（stdout）上列印出 "Hello, world!" 字串的簡單程式。類似的程式，通常作為初學程式語言時的第一個程式： 
1 #include <stdio.h>2 3 int main(void)4 {5     printf("Hello, world!\n");6     return 0;7 }

進一步了解

C語言由函式和變數組成，C的函式就像是Fortran中的子程式和函式。
在C語言中，程式從 main 開始執行。main 函式通過呼叫和控制其他函式進行工作。例如上面的printf。程式設計師可以自己寫函式，或從庫中呼叫函式。在上面的return 0; 使得 main 返回一個值給呼叫程式的殼層，表明程式是否成功執行。
一個C語言的函式由返回值、函式名、參數列和函式體組成。函式體的語法和其它的複合的語句部分是一樣的。

複合語句

C語言中的複合語句（或稱語句塊）的格式為：
{
    語句;
    語句;
    /* ... */}
複合語句可以使得幾個語句從文法上變成一個語句。
有時必須使用複合語句，否則會產生錯誤。例如，在運用迴圈語句的時候，如果迴圈體（即迴圈中執行部分）包含多個語句（以分號隔開），則必須使用花括號將他們合併成一個複合語句。如果不這麼做，系統僅把第一個分號前的內容看做迴圈體。
需要注意的是，部分C編譯器並不支援在任意位置使用複合語句。

條件語句

C語言有兩種條件語句形式，分別是if和switch。
If 的格式如下：
if(運算式) // 如果
    語句; 
// 有時還會有 else：else      // 否則
    語句;
運算式的值非零表示條件為真；如果條件為假，程式將跳過if處的語句，直接執行if後面的語句。但是如果if後面有else，則當條件為假時，程式跳到else處執行。if和else後面的語句可以是另個if語句，這種套疊式的結構，允許更複雜的邏輯控制流程得以實現。在一般情況下，else一定與最接近的if成對，因此常用括弧{}越過此限制。比較下面兩種情況：
if(邏輯表達)
    if (邏輯表達式)
        語句; 
    else
        語句;
1 if(邏輯表達式甲)2 {3     if(邏輯表達式乙)4         語句;5 }6 else 
7     語句;
要注意這裡的縮排和換行只用於方便閱讀。編譯器並不會根據縮排層級猜測 if 和 else 的對應關係。
switch通常用於對幾種有明確值的條件進行控制。它要求的條件值通常是整數或字元。與switch搭配的條件轉移是case。使用case後面的標值，控制程式將跳到滿足條件的case處一直往下執行，直到語句結束或遇到break。通常可以使用default把其他例外的情況包含進去。如果switch語句中的條件不成立，控制程式將跳到default處執行；如果省略default子句，則直接執行下一語句。switch是可以巢狀的。
switch(值){
  case 甲:
  case 乙:
    語句段1; // 甲乙都會執行
    // 更多語句…
    break;  // 跳轉到 switch 末尾處
  case 丙:
    語句段2;
    break; 
  default:  // 無論如何都會匹配
    語句段3;}
簡單的條件判斷也可用?:
運算式?值1:值2;如:
   a=b>c?b:c // 如果變數"b"的值大於變數"c" 把變數"b"的值賦予變數"a"

循環語句

C語言有三種形式的循環語句：
do 
    語句while(判断式); 

和:while(判断式) 
    語句;和:for(起始化; 判断式;運算式)
    語句;
在while和for中，語句將執行到表達式的值為零時結束。在do...while語句中，循環將至少被執行一次。這三種循環結構可以互相轉化：
for(起始化; 判断式;運算式)
    語句;
如果語句中不使用continue語句的話，相當於
初始化;while (判断式) {
    語句;
    運算式;}
當循環條件一直為真時，將產生無窮迴圈。

跳轉語句

跳轉語句包括四種：goto，continue，break和return。
goto 標記;
goto語句是無條件轉移語句，且標記必須在當前函式中定義，使用「標記:」的格式定義。程式將跳到標記處繼續執行。由於goto（特別是向回 goto 和長距離的 goto）容易產生閱讀上的困難，所以對新手應該儘量少用。GCC 編譯器拓展支援對指標 goto和巨集內 goto，一定程度上增強了 goto 的可讀性。
continue語句用在迴圈語句中，作用是結束當前一輪的迴圈，馬上開始下一輪迴圈。
break語句用在迴圈語句或switch中，作用是結束當前迴圈，跳到循環體外繼續執行。但是使用break只能跳出一層迴圈。在要跳出多重迴圈時，可以使用goto使得程式更為簡潔。
當一個函式執行結束後要返回一個值時，使用return。return可以跟一個運算式或變數。如果return後面沒有值，將執行不返回值。

結構資料類型

結構資料類型允許構造由多個基礎資料類型組合而成的複雜結構，結構資料類型為物件導向的藍本。以下的結構資料類型通過指標實現了二元樹結構：
1 typedef struct Bintree {2     int data;3     struct bintree *lchild; // left child of the node4     struct bintree *rchild; // right child of the node5 } bintree; // 自定义 bintree 类型
為結構資料類型定義變數時通常會用到動態記憶體分配：
1 #define mktree() (bintree *)malloc(sizeof(bintree)) // 分配该结构所需的内存单元数量2 bintree *tree;3 tree = mktree(); // 分配到 tree 指针4 tree->data = 1;5 tree->lchild = mktree();6 ...
由於C語言不具備自動垃圾收集（Garbage Collection）功能，使用完畢後呼叫free(treePtr)來釋放之前通過malloc(size)分配的記憶體。詳見以下指標章節。

指標

如果一個變數聲明時在前面使用 * 號，表明這是個指標型變數。換句話說，該變數儲存一個位址，而 *（此處特指單目運算子 *，下同。C語言中另有雙目運算子 * 表示乘） 則是取內容運算子，意思是取這個記憶體位址里儲存的內容。把這兩點結合在一起，可將 int *a;看作是 「*a 解得的內容類型為 int」，對更複雜的聲明也如此。指標是 C 語言區別於其他同時代高階語言的主要特徵之一。
指標不僅可以是變數的位址，還可以是陣列、陣列元素、函式的位址。通過指標作為形式參數可以在函式的呼叫過程得到一個以上的返回值（不同於return z這樣的僅能得到一個返回值。
指標是一把雙刃劍，許多操作可以通過指標自然的表達，但是不正確的或者過分的使用指標又會給程式帶來大量潛在的錯誤。
例如：
int *pi;     // 指向整型数据的指针 piint * api[3];// 由指向整型数据的指针构成的数组，长度为 3char ** argv;// 指向一个字符指针的指针struct { int member; } stinst,
  * pst = & stinst;// pst是一个指向一个匿名结构体的指针
儲存在指標中的位址所指向的數值在程式中可以由 * 讀取。例如，在第一個例子中， *pi 是一個整型資料。這叫做參照一個指標。
另一個運算子 &，叫做取位址運算子，它將返回一個變數、陣列或函式的儲存位址。因此，下面的例子：
int i, *pi; /* int and pointer to int */pi = &i;
i 和 *pi 在程式中可以相互替換使用，直到 pi 被改變成指向另一個變數的位址。
當指標指向結構體時，可以使用運算子 -> 代替 *和. 的作用，如 (*p).m 與 p->m 等效。

字串

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

檔案輸入／輸出

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

函式

C語言的基本結構單位是函式。系統首先呼叫 main函式（主函式），通過函式的巢狀呼叫，再呼叫其他函式。函式可以是系統內建的函式，也可以是用戶定義的函式。C語言中，不允許函式巢狀定義。

安全問題

C語言的特色之一是：語言不負責記憶體邊界檢查。此特性容易導致緩衝區溢位問題。

工具軟體

工具軟體可以幫助程式設計者避免一些程式中潛藏或容易出現的問題，例如常會造成程式未預期動作或是執行期錯誤的程式碼。
許多語言都有自動原始碼檢查及審計工具，C語言也有類似工具，像是Lint。可以在程式剛寫好時用Lint找出可能有問題的程式，通過Lint後再用C編譯器進行編譯，許多編譯器也可以設定是否要針對一些可能有問題的程式碼提出警告。MISRA C是一套針對嵌入式系統的法則，可主要也是避免一些可能有問題的程式碼。
也有一些編譯器、程式庫或作業系統可以處理一些非標準C語言的功能，例如邊界值檢查、緩衝區溢位偵測、序列化及自動垃圾回收功能。
使用像Valgrind或IBM Rational Purify等軟體工具，或者連結有特別malloc函式的程式庫，有助於找出一些運行期記憶體使用的問題。

經典錯誤

「void main()」的用法並不是任何標準制定的。 C語言標準語法是「int main()」，任何實現都必須支援int main(void) { /* ... */ }和int main(int argc, char* argv[]) { /* ... */ }。 在 C++ 標準中，main的標準型態應是int，否則類型是由實現定義的。任何實現都必須支援int main() { /* ... */ }和int main(int argc, char* argv[]) { /* ... */ }。