assert
assert是什么?
断言,是一个定义在<assert.h>中的一个宏,并非函数
void assert(int expression);//判断表达式的真假
assert能干什么?
- 用来检查数据的合法性,但是频繁的调用极大的影响程序的性能,增加了额外的开销(因为异常则直接中断abort)。
assert开发
- 断言的目的虽然是检测数据,但不意味着它需要出现在任何判断的地方,除了它系统消耗大以外,我们也要把握编程的平衡
名词引入:契约式编程
契约式设计强调三个概念:前置条件,后置条件和不变式。
前置条件发生在每个操作(方法,或者函数)的最开始,后置条件发生在每个操作的最后,不 变式实际上是前置条件和后置条件的交集。违反这些操作会导致程序抛出异常。 - 断言一般判断内容只为一个,为的是可以准确定位到错误的是哪个条件。当然你也可以配合&&一起使用,构成所谓的短路表达式,使得错误中断,可以打印出一定的信息。
int result = a / b; assert(b != 0 && "The divisor can not be zero");
- 断言只针对DEBUG版本,RELEASE版本时候需要将断言去掉,直接使用#define NDEBUG即可
#define NDEBUG //必须写在头文件前面 #include <assert.h>
必须写在头文件前面才可以生效,因为assert在头文件中是条件编译编码的,条件便是#ifndef NDEBUG,因此写在前面才能使得assert不能生效。
- 如果使用#define NDEBUG意味着assert不再提供功能,且里面的函数调用也不会运行,即不会有结果,因此使用中间变量接受函数返回值最佳。
- #undef 可以改写宏,此处可以使用吗?答案是不可以,因为改写之后就会报错assert未定义的引用,而#define NDEBUG不会出现这样的情况,因为assert会被“清除”掉。
源码
所有的问题,读了源码之后都不是问题
#undef assert
#ifdef __cplusplus
extern "C" {
#endif
#ifdef NDEBUG
/*
* If not debugging, assert does nothing.
*/
#define assert(x) ((void)0)
#else /* debugging enabled */
/*
* CRTDLL nicely supplies a function which does the actual output and
* call to abort.
*/
_CRTIMP void __cdecl __MINGW_NOTHROW _assert (const char*, const char*, int) __MINGW_ATTRIB_NORETURN;
/*
* Definition of the assert macro.
*/
#define assert(e) ((e) ? (void)0 : _assert(#e, __FILE__, __LINE__))
#endif /* NDEBUG */
#ifdef __cplusplus
}
#endif
#endif /* Not RC_INVOKED */