編譯時期斷言是一種讓編譯器在編譯階段檢查條件是否成立的技術。若條件為假,編譯器會直接報錯,從而將潛在錯誤提前暴露,避免其流入運行時期。這在大型專案(如 WebKit、Chromium)中極為常見,是提升代碼健壯性的關鍵手段。
static_assertC++11 引入了關鍵字 static_assert,語法為 static_assert(常量表達式, 錯誤訊息)。它不僅簡潔,還能自定義錯誤提示,大大提升了可讀性。例如:
static_assert(sizeof(int) == 4, "int 必須為 4 位元組");
在不支持 C++11 的環境中,開發者需自行構造非法代碼以觸發編譯錯誤。最經典的技巧是利用「負數組長度」:
#define COMPILE_ASSERT(exp, name) typedef int dummy##name[(exp) ? 1 : -1]
當 exp 為假時,陣列長度變為 -1,編譯器會報「陣列大小為負」錯誤。這利用了 C 標準禁止變長陣列(VLA)且大小必須為正的規定。
COMPILE_ASSERT 實戰WebKit 根據編譯器能力分級降級:
_Static_assert → 直接使用(兼容純 C 代碼)static_assert → 使用這種「特性檢測 + 降級策略」是跨平台庫的典型模式。
實現斷言本身不難,難點在於構造編譯期可計算的條件。WebKit 大量使用 sizeof 比較類型大小,以及靜態常量比較,因為這些值在編譯期確定。例如:
COMPILE_ASSERT(sizeof(MyStruct) == 16, MyStruct_size_check);
static_assert(C++11/C11 以上)。編譯時期斷言是「零成本」的安全網,善用它能讓無數潛在 Bug 在敲下編譯鍵的瞬間現形,是現代 C/C++ 開發不可或缺的利器。