首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C 標準庫 實現原理深度解析

     編輯:C++ 入門

背景知識

<assert.h> 僅提供 assert 巨集,用於在關鍵處檢查斷言。斷言失敗時輸出錯誤訊息至標準錯誤流並異常終止程式(呼叫 abort())。

範例:

#include <assert.h>
assert(0 <= i && i < sizeof(a)/sizeof(a[0]));

透過定義 NDEBUG 巨集可控制斷言啟用/停用:

  • 未定義 NDEBUG:assert 展開為活動形式,檢查條件,失敗時輸出檔案、行號、條件文本並 abort()。
  • 已定義 NDEBUG:assert 展開為 ((void)0),零開銷。

可在同一檔案中多次切換:

#define NDEBUG
#include <assert.h>   // 此後斷言關閉
#undef NDEBUG
#include <assert.h>   // 此後斷言開啟

assert 宏的標準實現

框架:

#undef assert
#ifdef NDEBUG
#define assert(expr) ((void)0)
#else
void __bad_assertion(const char *msg);
#define __str(x) #x
#define __xstr(x) __str(x)
#define assert(expr) ((expr) ? (void)0 : \
    __bad_assertion("Assertion \"" #expr "\" failed, file " __xstr(__FILE__) ", line " __xstr(__LINE__) "\n"))
#endif

關鍵技巧:

  • 使用 __FILE__、__LINE__ 內建巨集獲取位置。
  • __LINE__ 為數字常數,需雙層字串化(__str/__xstr)轉為字串字面量。
  • 條件運算子 ? 確保宏展開為 void 型別表達式,可用於任何語句位置。
  • 不直接呼叫 fprintf 等庫函式,避免未包含 <stdio.h> 時編譯錯誤;改呼叫隱藏函式 __bad_assertion。

隱藏函式 __bad_assertion 實現

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

void __bad_assertion(const char *mess) {
    fputs(mess, stderr);
    abort();
}

測試範例

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *fp = fopen("test.txt", "w");
    assert(fp);               // 成功
    fclose(fp);

    fp = fopen("noexit.txt", "r"); // 失敗,fp == NULL
    assert(fp);               // 觸發斷言失敗,程式終止
    return 0;                 // 不會執行到此
}

使用最佳實踐

  1. 檢查函數參數合法性:assert(nNewSize >= 0);
  2. 每個 assert 僅檢查單一條件,失敗時易定位:
    assert(nOffset >= 0); assert(nOffset+nSize <= m_nInfomationSize);
  3. 勿使用有副作用的表達式:assert(i++ < 100); 錯誤(Release 下 i 不增),應寫 assert(i < 100); i++;
  4. assert 與後續語句空一行,增強可讀性。
  5. assert 不能替代必要的錯誤處理(如使用者輸入檢查)。

參考資料

  • 《C 標準庫》 - P.J. Plauger
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved