斷言assert原型
void assert(int expression);
assert宏的原型定義在<assert.h>中,其作用是先計算表達式expression的值爲假(即爲0),那麼它就先向stderr打印一條出錯信息,然後通過條用abort來終止程序;
使用assert的缺點是,頻繁的調用會極大的影響程序的性能,增加額外的開銷。
在調試結束後,可以通過在包含#include 的語句之前插入 #define NDEBUG 來禁用assert調用,示例代碼如下:
1 #include
2 #define NDEBUG
3 #include
斷言assert使用規則
#include <stdio.h>
#include <assert.h>
int main(void)
{
int i;
i = 1;
assert(i++);
printf(“%d\n”,i);
return 0;
}
看運行結果,如果給定的i初始值爲1,所以其運行結果不會爲錯,如下圖所示
如果將i初始值改成0,那麼就會出現如下錯誤:
上面這個錯誤是很典型異常,可以考慮用assert排查。
根據提示我們很快就能定位到錯誤點,就在assert(i++)處;既然assert這麼便於定位出錯點,在工程中使用它就顯得很有必要;但其也有一定的使用規則;
斷言語句不會永遠被執行,可以屏蔽也可以啓用,這就要求assert不管是在屏蔽還是啓用狀態下都不能對我們本身代碼有所影響,這樣剛纔我們在代碼中使用的assert(i++)
就不行,因爲如果禁用了assert
,那i++就不能執行;正確的做法應該是:assert(i);i++;
那麼我們一般在什麼情況下使用斷言呢?
主要體現在以下幾個方面:
1. 可以在預計正常情況下程序不會到達的地方放置斷言。(如assert(0);)
2. 使用斷言測試方法的前置條件和後置條件;
前置條件:代碼執行前必須具備的特性;
後置條件:代碼執行後必須具備的特性;
3. 使用斷言檢測類的不變狀態,確保任何情況下,某個變量的狀態或範圍必須滿足。
斷言assert使用規則
當然我們在使用斷言的過程中會有一些我們應該注意的事項和養成一些良好的習慣,如:
1. 每個assert只檢驗一個條件,因爲同時檢驗多個條件時,如果斷言失敗,我們就無法直觀的判斷哪個條件失敗;
無法直觀的判斷哪個條件失敗:
assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
只檢驗一個條件,比較直觀:
assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);
2. 不能使用改變環境的語句,就像我們上面的代碼改變了i變量,在實際編寫代碼的過程中是不能這樣做的;
例如:
assert(i++ < 100)
不好:這是因爲如果出錯,比如在執行之前i=100,那麼這條語句就不會執行,那麼i++這條命令就沒有執行。
assert(i < 100)
i++;
正確。
3. assert和後面的語句應該空一行,以形成邏輯和視覺上的一致性,也算是一種良好的編程習慣,讓編寫的代碼有一種視覺上的美感;
4. 有的地方,assert不能代替條件過濾;
程序一般分爲Debug 版本和Release 版本,Debug 版本用於內部調試,Release 版本發行給用戶使用。斷言assert 是僅在Debug 版本起作用的宏,它用於檢查"不應該"發生的情況。
5. 放在函數參數的入口處檢查傳入參數的合法性;
int resetBufferSize(int nNewSize)
{
//功能:改變緩衝區大小,
//參數:nNewSize 緩衝區新長度
//返回值:緩衝區當前長度
//說明:保持原信息內容不變 nNewSize<=0表示清除緩衝區
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
...
}
在我們使用C語言/C++做工程項目時,如果我們能在代碼中合理的使用assert,能使我們創建更穩定、質量更好且不易於出錯的代碼;當需要在一個值爲FALSE時中斷當前操作的話就可以使用斷言。
單元測試必須使用斷言;另外除了類型檢查和單元測試外,斷言還提供了一種確定各種特性是否在程序中得到維護的極好的方法;
最近原創推薦:
點【在看】是最大的支持