断言(assert)
断言(assert)是一行检查表达式的代码;当表达式求值为真,一切正常;但若表达式求值为假,则暂停程序,打印消息,并在可行的情况下启动调试器。
断言(assert)是一个宏,而非函数。
断言的使用
#include <assert.h>
using namespace std;
float division(float a, float b)
{
assert(b != 0);
return a / b;
}
int main()
{
float a = 10;
float b = 0;
division(a,b);
return 0;
}
断言的实现
#if ASSERTIONS_ENABLED
#define debugBreak() asm{ int 3;}
#define ASSERT(expr) \
if(expr){}
else {
reportAssertionFailure(#expr,__FILE__,__LINE__);
debugBreak();
}
#else
#define ASSERT(expr)
#endif
其运行过程如下:
- 外层的#if 、 #else、 #endif 用于剥除代码的断言;如果开启assert,ASSERT的宏就被定义为真正版本,所有断言检查就会生效,否则ASSERT 就不做任何事,实际上会被处理器删除。
- debugBreak定义为一些汇编指令,这些指令会暂停程序(如果在调试执行,就把控制权转给调试器);这个指令因CPU而异。
- ASSERT 本身用完整的if/else语句,因为这是个宏定义;如果只使用if 语句,当assert在if 、else 的过程中使用,宏展开将会产生问题。
- ASSERT()语句中做了两件事:一是显示出错信息,二是中断程序;并用__FILE__ 和 __LINE__ 宏来显示出错的文件以及位置。
以下为visual studio 中的源码:
#ifdef NDEBUG
#define assert(expression) ((void)0)
#else
_ACRTIMP void __cdecl _wassert(
_In_z_ wchar_t const* _Message,
_In_z_ wchar_t const* _File,
_In_ unsigned _Line
);
#define assert(expression) (void)( \
(!!(expression)) || \
(_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
)
#endif