一直以來,對於assert的實現老是不太理解,如今深刻assert背後的代碼,總算對assert的實現有了一個清醒的認識。函數
assert基於宏定義與宏展開實現。首先介紹一下assert的功能:它可以斷言給定表達式是否爲true。若是爲true,則對應assert的代碼會轉換爲static_cast<void>(0)
,即一條空語句,assert不執行任何操做,不然assert對應的代碼會展開爲__assert_fail (__STRING(expr), __FILE__, __LINE__, __func__))
,使用expr參數,源代碼名,assert所在的行數以及函數名調用__assert_fail
函數,輸出錯誤信息,而且由於斷言出錯而終止程序。請注意,在調用函數__assert_fail
時,assert將傳入的參數轉換爲字符串輸入,這一點只需查看__STRING(x)
的定義:#define __STRING(x) #x
便可明白。code
咱們知道,在編譯源代碼的時候,若是咱們定義了NDEBUG
,那麼assert不會起任何做用,哪怕傳入的參數爲false
,這是爲何呢?由於在assert外層還有一個宏判斷語句,若是定義了NDEBG
,那麼assert語句統一轉換成static_void<void>(0)
進行處理,因此不會對傳入的參數進行任何判斷。字符串
下面附上相關代碼,相信你如今會對assert有更加清晰的認識!編譯
// (爲了便於閱讀,代碼進行了部分修改) #define __STRING(x) #x #ifdef NDEBUG # define assert(expr) (static_cast<void>(0)) #else # define assert(expr) \ ((expr) \ ?static_cast<void>(0) \ : __assert_fail (__STRING(expr), __FILE__, __LINE__, __func__)) #endif