<assert.h> 是 C 標準函數庫中極具特色的標頭檔,提供 assert() 宏用於程式除錯。其獨特之處在於可重複引入並根據 NDEBUG 宏產生不同行為。
void assert(int expression);
abort() 終止程式__FILE__ 宏)__LINE__ 宏)__func__,C99 新增)| 程式類型 | 診斷輸出目標 |
|---|---|
| 控制台程式 | stderr 標準錯誤裝置 |
| 視窗程式 | Windows MessageBox 對話框 |
無需修改原始碼即可屏蔽所有斷言:
-DNDEBUG(GCC/Clang)或 /DNDEBUG(MSVC)#include <assert.h> 前定義:#define NDEBUG重要:被停用的 assert() 甚至不會對參數表達式求值,因此參數不可包含副作用(如 assert(x++ > 0) 會導致釋出版本邏輯錯誤)。
#include <stdio.h>
#include <assert.h>
int main(void) {
FILE *fd = fopen("/home/user/file.txt", "r");
assert(fd); // 若 fd 為 NULL,程式終止並輸出診斷資訊
fclose(fd);
return 0;
}
// 未定義 NDEBUG
#include <stdio.h>
#include <assert.h>
int main() {
printf("1 ok hello\n");
assert(1 == 4); // 觸發斷言失敗
printf("2 ok exit\n"); // 不會執行
return 0;
}
/* 輸出:
1 ok hello
assert_h_ex.c:7: main: Assertion `1==4' failed.
Aborted
*/
// 定義 NDEBUG
#include <stdio.h>
#define NDEBUG
#include <assert.h>
int main() {
printf("1 ok hello\n");
assert(1 == 4); // 被忽略
printf("2 ok exit\n"); // 正常執行
return 0;
}
/* 輸出:
1 ok hello
2 ok exit
*/
#define assert(test) if(!(test)) \
fprintf(stderr, "Assertion failed: %s, file %s, line %d\n", \
#test, __FILE__, __LINE__), \
abort()
利用字串化運算子 # 將表達式轉為字串,配合 __FILE__、__LINE__ 定義宏。
#define Assert(test) if(!(test)) \
fprintf(stderr, "Assertion failed: %s, file %s, line %d\n", \
#test, __FILE__, __LINE__), \
abort()
行為與標準 assert() 類似,但不受 NDEBUG 控制,適合需永久保留的關鍵檢查。
NDEBUG 確保零效能負擔if 而非 assert