位元詩人 語言延伸實例:自動檢查 C 和 C++ 程式碼

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

說明

靜態程式碼檢查是現代語言的標準功能之一。Golang 內建 go vet 指令,Rust 也會在編譯時自動執行檢查。

相較之下,C 和 C++ 雖然同樣具備靜態檢查能力,但預設並不會啟用,必須手動加上參數。例如:

$ gcc -std=c11 -pedantic -Wall -Wextra -fsyntax-only program.c

這類指令本身並不複雜,但在實務上有兩個問題:

  • 指令冗長,容易重複輸入
  • 一旦涉及多檔案或 C / C++ 混合專案,處理方式會變得零散

進一步來看,C / C++ 編譯器本身並沒有提供多檔案管理機制。當程式規模稍微增加時,往往需要引入 Make、CMake 等 build automation 工具,才能維持可操作性。

這就形成一個常見但容易被忽略的落差:

為了做一件很單純的事情(檢查 warning),卻需要啟動一整套建構系統。

問題並不在於工具不足,而在於成本與需求之間出現了錯配。

本文介紹一個簡單的 POSIX sh 命令稿 ccwarn,用來自動化這個過程,在不引入專案設定的前提下,完成 C 與 C++ 的靜態檢查。

使用範例

$ ccwarn main.c model.c utils.c

ccwarn 會自動呼叫 GCC 與 Clang,對所有檔案進行檢查。

這樣的做法有兩個直接效果:

  • 不需要撰寫 build automation 命令稿
  • 可以同時檢查不同編譯器下的行為差異

由於 GCC 與 Clang 在診斷與語言擴充上存在差異,透過兩者交叉檢查,可以降低無意間依賴特定編譯器行為的風險。

在不同作業系統(例如 GNU/Linux 與 FreeBSD)下執行時,也能順便觀察是否引入平台相關特性(例如 Linux-only 行為)。

需要注意的是,ccwarn 的設計目標並不包含大型或複雜專案。對於這類情境,完整的 build automation 工具仍然是更合適的選擇。

為什麼要製作這個指令

ccwarn 並沒有引入新的語言特性,也不試圖取代既有的工具鏈。

它的定位更接近於:

在既有編譯器之上,加上一層局部的 abstraction。

這層 abstraction 並不改變語言,也不改變編譯器本身,而是重新整理「如何使用它們」的方式。

在學習 C 或 C++ 的過程中,常見的情境是:

  • 撰寫短小的練習程式
  • 驗證語法或語言特性
  • 不打算建立長期維護的專案

在這些情況下,為每一份程式碼建立專案、設定 build automation,成本往往高於實際需求。

ccwarn 將問題重新定義為:

「這段程式碼,能否在不同編譯器下乾淨地編譯?」

當問題被壓縮到這個程度時,對應的解法也可以變得非常簡單:

  • 不需要專案設定
  • 不處理相依性
  • 不涉及執行期行為

換句話說,它不是在增加功能,而是在移除不必要的負擔

這樣的設計,使 ccwarn 特別適合用於:

  • 小型程式碼
  • 快速實驗
  • warning 清理
  • 可攜性檢查

相對地,在大型專案中,這些問題通常已由既有的 build system 解決,ccwarn 也就不再是主要工具。

結語

ccwarn 並不是為了取代既有工具鏈而存在。

它的價值在於示範另一種思路:

當問題本身足夠小時,未必需要引入更大的工具或改變整個環境;有時,只需要在既有基礎之上,加上一層薄薄的 abstraction,就足以改善開發體驗。

這樣的做法,或許不顯眼,但在實務中往往更直接,也更具成本效益。

另見

本專案位於 https://github.com/opensourcedoc/ccwarn

關於作者

位元詩人 (ByteBard) 是資訊領域碩士,喜歡用開源技術來解決各式各樣的問題。這類技術跨平台、重用性高、技術生命長。

除了開源技術以外,位元詩人喜歡日本料理和黑咖啡,會一些日文,有時會自助旅行。