c語言標準庫詳解(十):診斷函數<assert.h>
概述
<assert.h>中只有一個assert宏。
assert宏用於爲程序增加診斷功能,形式如下:
void assert(int expression)
如果執行語句
assert(expression)
時,表達式的值爲0,則assert宏將在stderr中打印一條消息,比如:
Assertion failed:表達式,file 源文件名,line 行號
打印消息後,該宏將調用abort終止程序的執行。其中的源文件和行號來自於預處理器宏__FILE__以及__LINE__。
如果定義了宏NDEBUG,同時又包含了頭文件<assert.h>,則assert宏將被忽略。
示例
代碼
#include <assert.h>
#include <stdio.h>
int main()
{
int a;
char str[50];
printf("請輸入一個整數值: ");
scanf("%d", &a);
assert(a >= 10);
printf("輸入的整數是: %d\n", a);
printf("請輸入字符串: ");
scanf("%s", str);
assert(str != NULL);
printf("輸入的字符串是: %s\n", str);
return(0);
}
不同的輸入與輸出
PS G:\CSAPP> & 'c:\Users\swy\.vscode\extensions\ms-vscode.cpptools-0.27.1\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-ce44jt01.wkp' '--stdout=Microsoft-MIEngine-Out-z401vdid.zwc' '--stderr=Microsoft-MIEngine-Error-bzwjf2pm.eif' '--pid=Microsoft-MIEngine-Pid-ceq5e0lw.rgk' '--dbgExe=G:\x86_64-8.1.0-release-posix-sjlj-rt_v6-rev0\mingw64\bin\gdb.exe' '--interpreter=mi'
請輸入一個整數值: 9
Assertion failed!
Program: G:\CSAPP\exercise.exe
File: g:\CSAPP\languageC\exercise.c, Line 11
Expression: a >= 10
PS G:\CSAPP>
PS G:\CSAPP> & 'c:\Users\swy\.vscode\extensions\ms-vscode.cpptools-0.27.1\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-bksgqqtk.pn1' '--stdout=Microsoft-MIEngine-Out-ifhvr50v.2wj' '--stderr=Microsoft-MIEngine-Error-jy0bmmwd.a2a' '--pid=Microsoft-MIEngine-Pid-2ihgcj2f.q4x' '--dbgExe=G:\x86_64-8.1.0-release-posix-sjlj-rt_v6-rev0\mingw64\bin\gdb.exe' '--interpreter=mi'
請輸入一個整數值: 11
輸入的整數是: 11
請輸入字符串: long live open source
輸入的字符串是: long
PS G:\CSAPP>
注意
- ASSERT 只有在 Debug 版本中才有效,如果編譯爲 Release 版本則被忽略。
- 頻繁的調用會極大的影響程序的性能,增加額外的開銷。
- 每個assert只檢驗一個條件,因爲同時檢驗多個條件時,如果斷言失敗,無法直觀的判斷是哪個條件失敗,如下:
assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
改爲:
assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);
- 不能使用改變環境的語句,因爲assert只在DEBUG個生效,如果這麼做,會使用程序在真正運行時遇到問題,如下:
assert(i++ < 100);
改爲:
assert(i < 100)
i++;
- assert和後面的語句應空一行,以形成邏輯和視覺上的一致感。
- 有的地方,assert不能代替條件過濾。
- assert是一個宏,而非函數
- 在調試結束後,可以通過在包含 #include 的語句之前插入 #define NDEBUG 來禁用 assert 調用,示例代碼如下:
#include
#define NDEBUG
#include
用途
- 在函數開始處檢驗傳入參數的合法性 。
- 契約式編程。