assert.h

assert.h

assert.h常用於防禦式編程。斷言(Assertions),一個斷言通常是一個例程(routines)或者一個宏(marcos)。每個斷言通常含有兩個參數:一個布爾表示式(a boolean expression)和一個訊息(a message)。

基本介紹

  • 外文名:assert.h
  • 常用於防禦式編程
  • 參數:布爾表示式,訊息
  • 特點:可以使用斷言
assert.h assert.h常用於防禦式編程
斷言(Assertions)
一個斷言通常是一個例程(routines)或者一個宏(marcos)。每個斷言通常含有兩個參數:一個布爾表示式(a boolean expression)和一個訊息(a message)。一個布爾表達式的反面表示了一個錯誤。C 標準庫提供了一個 assert 宏,它只帶有一個參數,用法如下:
assert(1 == 0); // 注意 boolean expression 不要加引號
使用 assert 宏,需要包含頭檔案 cassert 或者 assert.h,執行上面語句的結果是程式終止運行,輸出與下面訊息類似的訊息:
Assertion failed: 1 == 0, file d:\我的文檔\visual studio projects\learning\assert\assert.cpp, line 9
通常來說,我們會定義自己的 assert 宏,其目的有兩個:
(1)新增參數,例如新增一個訊息參數,使得 assert 宏輸出更為豐富的信息。
(2)改變 assert 的行為內容。C 標準庫中的 assert 宏將中斷程式,實際上,我們可以讓程式繼續運行而不中斷或者進入調試狀態等,另外還可以控制訊息輸出的目標,即控制訊息是輸出到控制台還是文本檔案,甚至是通過網路發出。
下面是一個 C++ 實現的斷言:
#define Assert(exp, message) \
{ \
if (!(exp)) \
{ \
std::cout << "Assertion failed: " << #exp << "\n" \
<< "Message: " << message << "\n" \
<< "line: " << __LINE__ << "\n" \
<< "file: " << __FILE__ << "\n"; \
exit(EXIT_FAILURE); \
} \
}
#else
#define Assert(exp, message)
執行 Assert(1 == 0, "Error"); 結果為:
Assertion failed: 1 == 0
Message: Error
line: 24
file: d:\我的文檔\visual studio projects\learning\assert\assert.cpp
使用斷言應該注意一下的幾個問題:
1)對非預期錯誤使用斷言
斷言中的布爾表達式的反面一定要描述一個非預期錯誤,下面所述的在一定情況下為非預期錯誤的一些例子:
(1)空指針
(2)輸入或者輸出參數的值不在預期範圍內。
(3)數組的越界。
非預期錯誤對應的就是預期錯誤,我們通常使用錯誤處理代碼來處理預期錯誤,而使用斷言處理非預期錯誤。在代碼執行過程中,有些錯誤永遠不應該發生,這樣的錯誤是非預期錯誤。斷言可以被看成是一種可執行的注釋,你不能依賴它來讓代碼正常工作。例如:在
int nRes = f(); // nRes 由 f 函式控制, f 函式保證返回值一定在 -100 ~ 100
Assert(-100 <= nRes && nRes <= 100); // 斷言,一個可執行的注釋
由於 f 函式保證了返回值處於 -100 ~ 100,那么如果出現了 nRes 不在這個範圍的值時,就表明一個非預期錯誤的出現。後面會講到“隔欄”,那時會對斷言有更加深刻的理解。
2)不要把需要執行的代碼放入斷言中
斷言用於軟體的開發和維護,而通常不在發行版本中包含斷言。
需要執行的代碼放入斷言中是不正確的,因為在發行版本中,這些代碼通常不會被執行,例如:
Assert(f()); // f 函式通常在發行版本中不會被執行
而使用如下方法則比較安全:
res = f();
Assert(res); // 安全
3)對來源於內部系統的可靠的數據使用斷言,而不要對外部不可靠的數據使用斷言,對於外部不可靠數據,應該使用錯誤處理代碼。再次強調,把斷言看成可執行的注釋。
前條件(preconditions)和後條件(postconditions)
前條件是調用方代碼在調用例程(routines)或者實例化對象之前要確保為真的條件,後條件是例程執行後或者類實例化後應滿足的條件。下面是一個例子:
// 前條件,這裡 nNum1 和 nNum2 的取值被前面代碼所約束並保證取值在 -50 ~ 50
Assert(-50 <= nNum1 && nNum1 <= 50, "Add_nNum1");
Assert(-50 <= nNum2 && nNum2 <= 50, "Add_nNum2");
int nRes = add(nNum1, nNum2);
// 後條件
Assert(-100 <= nRes && nRes <= 100, "Add_nRes");
注意,由於 nNum1 和 nNum2 取值範圍已經被約束,因此可以使用斷言,但是如果 nNum1 和 nNum2 的值來源於不可靠的外部系統,那么應該使用錯誤處理代碼,而不是使用斷言。

相關詞條

熱門詞條

聯絡我們