C語言版本完整指南|從C89到C23的特點、差異與選擇徹底解析

1. 為什麼「C 語言 版本」很重要

C 語言自 1970 年代誕生以來,作為程式語言的基礎被廣泛使用。在那漫長的歷史中,制定了各種版本(標準),持續演進。 但是,C 語言的「版本是什麼意思? 為什麼需要意識到版本? C 語言因長期以來被廣泛用於許多系統與應用程式的開發,所以「程式碼是以哪個版本為前提撰寫的」以及「使用的編譯器遵循哪個版本」這些點,對程式碼相容性可移植性,甚至可維護性都有重大影響。 實際上,C 語言的標準(版本)隨著時代進,會加入新功能與規範,並修正或廢除舊有規範。 例如「可變長度陣列」或「bool 型別」以及「執行緒相關的標準化」等,在舊版本中不存在,只有在一定以上的版本才能使用。 相反地,若使用新標準的編譯器編譯以舊規格撰寫的原始碼,可能會出現意想不到的錯誤或警告。 在本文中,將從「為什麼重要」的觀點,說明 C 語言的版本, ・各版本的差異 ・主要特點 ・實務上的選擇方式 ・以及最新的動向 將以易於理解的方式說明到此為止。期望本內容能對剛開始學習 C 語言的人、以及在現場使用的工程師,提供整理版本基礎知識的幫助。

2. C 語言版本的基本結構與規格/編譯器的關係

C 語言的「版本」聽起來,程式設計初學者可能會有點混亂。 因為「版本」實際上有兩層含義。 一個是,C 語言本身的規格(標準規範)作為的版本。另一個是,C 語言編譯器軟體的版本

C 語言規格(標準規範)的版本是什麼?

C 語言的標準規格是由國際標準化組織(ISO)以及美國國家標準協會(ANSI)等制定的。 每個規格都有「C89」「C99」「C11」「C17」「C23」等版本名稱。 這些版本規定了「可以怎樣寫程式」「具備哪些功能」「會有什麼行為」等,C 語言程式的規則本身

編譯器的版本是什麼?

另一方面,用於編寫 C 語言程式的「編譯器」(例如 GCC、Clang、Visual Studio 等)也各自有軟體版本。 編譯器決定了「支援到哪個 C 語言規格」,較新的編譯器會支援較新的規格。 例如,GCC 依版本支援 C99、C11、C17 等,而 Visual Studio 從 2019 版之後也能使用許多 C11 功能。

先弄清規格與編譯器的差異

  • C 語言規格的版本=語言的規則手冊
  • 編譯器的版本=遵循規則手冊的程度,以及提供功能的軟體演進
這兩者密切相關,但並非相同的東西。 例如,即使編譯器是新的,也可能包含未遵循規格的功能或自行擴充的特性。 在 C 語言開發時,意識「程式碼遵循哪個規格」以及「使用的編譯器支援到哪個程度」有助於避免問題並確保可移植性
年収訴求

3. C語言版本列表與演變

C語言自誕生以來,多次進行標準的修訂。每個版本都有其特色的功能新增或規格變更。在此,我們將依時間順序說明主要的版本。

3.1 C89/C90(ANSI C/ISO C)

最初被標準化的C語言是「C89(ANSI X3.159-1989)」。它由美國國家標準協會(ANSI)制定,之後幾乎相同內容由國際標準化組織(ISO)以「C90(ISO/IEC 9899:1990)」發佈。 特點:
  • 標準函式庫與語言規格被明確化,C語言程式的可移植性大幅提升
  • 從先前的“K&R C”起,函式宣告方式、型別檢查等變得更嚴格
  • 基本語法與許多標準函式在此階段被整理
此外,1995年加入了「C95(ISO/IEC 9899/AMD1:1995)」的修正版。C95是一個針對寬字元支援、國際化以及若干錯誤修正的小規模更新。

3.2 C99(ISO/IEC 9899:1999)

C99 是大幅推進 C 語言現代化的標準。加入了許多提升程式設計師便利性的功能。 主要新增與變更點:
  • 可變長度陣列(VLA)
  • 使用 // 的單行註解
  • 引入標準的 bool 型別與 long long int 型別
  • 內聯函式 inline
  • 支援複數(complex 數)
  • 初始化子更彈性的寫法(如陣列的中括號初始化等)

3.3 C11(ISO/IEC 9899:2011)

C11 是加強對現代開發環境與平行處理支援的標準。 主要新增與變更點:
  • 執行緒(多執行緒)的標準化(<threads.h>
  • 原子操作與記憶體模型(提升平行處理的安全性)
  • 加入靜態斷言 _Static_assert
  • 泛型巨集 _Generic
  • 對齊控制與 Unicode 支援的強化
然而,由於部分編譯器尚未實作執行緒等功能,實際使用時需特別留意。

3.4 C17/C18(ISO/IEC 9899:2018)

C17(亦稱為 C18)主要是 C11 的錯誤修正與次要規格調整,沒有新增大型功能。 特點:
  • 以錯誤修正與模糊規格的釐清為主
  • 在實務上與 C11 幾乎相同地使用

3.5 C23(ISO/IEC 9899:2024)

C23 是於 2024 年正式化的最新標準。受到近年其他語言趨勢與程式開發需求的影響,導入了大量新功能。 主要新增與變更點:
  • 加入 nullptr 關鍵字(提升與 C++ 的相容性)
  • 引入二進位字面值(例如:0b1010
  • 支援 char8_t 型別(明確的 UTF-8 型別)
  • 新增與統一標準屬性
  • 加強位元操作函式
  • 為提升可讀性而進行細部語法改良
預計 C23 將成為未來 C 語言開發的標準,但需留意編譯器的支援情況。 以上即為主要的 C 語言版本演變。接下來的章節將說明如何在實務上選擇與運用這些版本。

4. 各版本的選擇方式與實務建議

C 語言有多個規格版本存在,但在實際撰寫程式時,意識「使用哪個版本」是很重要的。這裡將說明現場的版本選擇考量、常見問題的避免方法,以及在實務上有用的技巧。

版本選擇的基本方針

1. 原則上優先使用較新的規格

如果可能,建議使用較新的規格(C11、C17、C23)。較新的規格已針對錯誤修正、提升安全性以及改善程式設計的便利性。

2. 配合既有程式碼與使用環境

然而,在既有系統、函式庫、嵌入式開發等情況下,往往需要配合較舊的規格(C90/C99)。此外,嵌入式用途也可能受到編譯器支援狀況的限制。

如何檢查規格符合性

在 C 語言中,使用前處理器巨集 __STDC_VERSION__ 可以簡單判斷編譯器支援哪個規格。
#include <stdio.h>

int main(void) {
#if __STDC_VERSION__ >= 202311L
    printf("C23 (ISO/IEC 9899:2024)支援n");
#elif __STDC_VERSION__ >= 201710L
    printf("C17/C18支援n");
#elif __STDC_VERSION__ >= 201112L
    printf("C11支援n");
#elif __STDC_VERSION__ >= 199901L
    printf("C99支援n");
#elif __STDC_VERSION__ >= 199409L
    printf("C95支援n");
#else
    printf("C89/C90支援n");
#endif
    return 0;
}
如此一來,使用 __STDC_VERSION__ 巨集即可確認各環境的規格版本。

實務上常見的注意事項

  • 確認編譯器的支援狀況 並非所有編譯器都完全支援最新規格。例如,GCC 與 Clang 會較快支援較新的規格,但 Visual Studio 與嵌入式編譯器的支援可能較慢。
  • 有時需要指定選項 某些編譯器若未在命令列選項中明確指定規格版本,則無法使用新功能。例如:gcc -std=c11 sample.c
  • 考量可移植性與維護性 在大型開發或長期運營的專案中,為了優先考慮維護性與可移植性,可能會刻意使用較舊的規格。

版本選擇的實踐指南

  • 新專案或學習用途:建議使用 C11 或 C17
  • 嵌入式或舊系統相容:C99 與 C90 也是選項
  • 想積極使用最新功能:在調查 C23 支援狀況後再考慮
  • 多人、多環境開發:事先共享所有人的編譯器支援狀況
透過意識 C 語言的規格版本並加以區分使用,可預防錯誤與不相容的問題。請依照現場情況與專案目標,選擇最適合的版本。

5. 未來的趨勢與 C23 之後

C 語言隨著時代的變遷持續演進。2024 年,C23 終於正式獲得國際標準的認可。本文將說明 C23 的重點以及未來 C 語言標準的展望。

C23 的正式化與主要新功能

C23(ISO/IEC 9899:2024)為了因應現代需求,加入了許多功能與改進。以下列出主要的新功能與改良點。
  • 新增 nullptr 關鍵字 與 C++ 相同,現在可以將 nullptr 作為「指標的明確 NULL 值」使用。這提升了可讀性,也有助於防止錯誤。
  • 引入二進制字面值 在此之前 C 語言無法直接表示二進制,但從 C23 起可使用如 0b1010 的二進制字面值。
  • 新增 char8_t 型 加入專為 UTF-8 設計的字元型別 char8_t,使多位元組字元的處理更直觀。
  • 加強標準屬性與位元操作函式 提供了更注重程式碼可讀性與最佳化的屬性,以及擴充的位元操作標準函式。
  • 細部語法與功能的改進 包含許多針對錯誤處理、安全性以及符合現代程式設計風格的改良。

C23 的採用情況與未來的普及

由於 C23 於 2024 年剛剛公布標準,尚未能立即在所有編譯器與開發環境中使用。開源編譯器如 GCC、Clang 正在逐步支援 C23,但完整實作與普及仍需時間。 在可預見的未來,C11 與 C17 仍將是主流。然而,預計在未來數年內,主要編譯器將加速支援,使利用 C23 功能的現代開發風格得以普及。

未來的 C 語言展望

C 語言已具備相當穩定的規格,甚至被稱為「老舊語言」,但預計仍會持續根據使用者需求與其他語言的趨勢逐步演進。AI、IoT、嵌入式開發等領域的需求仍然強勁,未來持續關注「C 語言版本」仍具重要意義。 此外,未來很可能會持續定期進行標準修訂,保持對最新動向的關注,有助於在實務上取得優勢並避免問題。

6. 總結

C 語言自誕生以來已接近半個世紀,至今仍廣泛應用於許多系統與軟體開發現場。其背後是作為「C 語言 版本」累積的眾多標準修訂與演進。 本文廣泛說明了 C 語言各版本的特點與變遷,以及實務上的選擇方式與注意事項,甚至涵蓋最新標準 C23 的動向。

意識版本的好處

  • 提升維護性 明確了解所基於的標準,可使未來的維護與規格變更的因應更為容易。
  • 確保可移植性 在不同開發環境或編譯器之間,程式碼的重用與共享更為容易。
  • 預防問題 即使在將舊程式碼移植至新環境,或使用新功能時,事先了解版本差異即可避免意外的錯誤與不相容問題。

實務上可活用的版本選擇

對於初學者而言,從功能完整且參考資訊豐富的「C99」或「C11」開始學習較為實際。 在實務開發時,請依據所使用的編譯器與既有系統的相容性,選擇最適的版本。

將目光放在現代 C 語言的升級上

雖然像 C23 這樣的最新標準在實務導入上需要時間,但它有助於未來程式設計的效率提升與安全性增進。 未來仍需關注 C 語言版本的演進,並視需求持續更新知識與技能。 正確理解「C 語言 版本」,並依情況作出選擇與運用,才能促成更安全且高效的開發。 若本文能成為各位在實務或學習上的參考,將不勝感激。

7. FAQ(常見問題)

在此,我們彙總了關於「C 語言 版本」的常見問題及其回答。從初學者到現場工程師,精選了有助於解決疑惑的內容。

Q1. 編譯器的版本與 C 語言標準的版本是一樣的嗎?

A. 不同。 C 語言標準的版本是「語言規範本身」的基準,像是「C99」「C11」「C23」等。另一方面,編譯器的版本則顯示該軟體的演進程度。 例如即使是 GCC 或 Clang 的最新版本,若未明確指定「-std=c11」等,仍可能不會進入符合標準的模式,請特別留意。

Q2. 舊的標準(C90 與 C95)現在仍有學習的意義嗎?

A. 有的。 即使在現在,許多企業與嵌入式開發現場仍重視相容性與遺留資產,採用符合 C90 或 C95 標準的開發。了解過去的標準對於故障排除與維護工作必定有幫助。

Q3. 最新標準 C23 應該立即使用嗎?

A. 需要謹慎判斷。 C23 剛於 2024 年正式定稿,尚未在所有編譯器與開發環境中完全支援。對於新專案或個人學習,先行嘗試使用也是不錯的,但在實務上務必確認編譯器的支援狀況以及整個團隊的開發環境。

Q4. __STDC_VERSION__ 的值能判斷自己的環境符合哪個標準嗎?

A. 可以,能判斷。 __STDC_VERSION__ 是一個顯示編譯器所支援的 C 語言標準版本的巨集。 主要的值例如如下:
巨集值標準名稱
199409LC95
199901LC99
201112LC11
201710LC17/C18
202311LC23

Q5. Visual Studio 與 GCC 支援哪些標準?

A. 各編譯器的支援情況各不相同。 例如 GCC 與 Clang 對較新的標準(C11、C17、C23)支援較快,但 Visual Studio 只支援 C11 之後的部分功能。嵌入式編譯器的支援情況更為參差不齊,建議於官方文件中確認最新資訊。

Q6. C++ 與 C 語言的版本差異是什麼?

A. C++ 是以 C 語言為基礎發展的另一種語言,版本管理與新功能的加入方針也不同。 C++ 的標準(C++98、C++11、C++17 等)與 C 語言同步演進,但因相容性並非完全,若以相同的感覺使用則可能有風險。

Q7. 我在猶豫該學哪個版本,建議是什麼?

A. 除非有特別原因,建議從 C99 或 C11 開始學習。 資訊量豐富且在現場廣泛使用,學習效率較高。若要進入嵌入式或特定領域,請依工作環境與開發需求選擇適合的版本。 希望本 FAQ 能協助解決疑問並在實務上提供幫助。 深入了解 C 語言的版本,讓程式設計更安全、更有效率。
侍エンジニア塾