断言(assert)作为一种程序调试的重要手段。
c++的<cassert>和<assert>头文件中assert宏的代码如下:
#undef assert
#ifdef NDEBUG
#define assert(_Expression) ((void)0)
#else /* NDEBUG */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
_CRTIMP void __cdecl _wassert(_In_z_ const wchar_t * _Message, _In_z_ const wchar_t *_File, _In_ unsigned _Line);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )
#endif /* NDEBUG */
通过上面代码分析可知:
(1)assert宏只在debug模式下有效,release模式下无效。
(2)只有表达式为true的情况下才有效。
此外两次取反可以保证取值最后为0或者1。
那么断言发生时,程序会怎么样?首先会向stderr打印处错误信息,然后调用abort来终止程序运行。
实际代码测试下:
#include <cassert>
int main()
{
assert(1 == 0);
return 0;
}
debug下运行效果如下:
错误信息包括了:断言表达式,断言所在的文件和行数。
assert固然好用,但是毕竟只有在程序运行时才能知道我们的程序是否健壮,我们希望能在编译时就能验证,因此C++11中增加了static_assert,,static_assert接收两个参数,第一个是断言表达式,这个表达式需要返回一个bool值;另外一个则是警告信息,通常是一段字符串。
下面我们在代码中验证一下:
#include <cassert>
int main()
{
static_assert(1 == 0, "static_assert occurs");
return 0;
}
这时候会神奇的发现代码编译不过,提示的错误描述居然是我们的第二个参数 “static_assert occurs“
static_assert的断言表达式结果必须是在编译器可以计算的表达式,即必须是常量表达式。如果使用了变量,则会导致错误。