一、定义
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型为:
void assert( int expression ); |
说明:assert()函数的作用是断言表达式expression,如果其值为假,那么它先向stderr打印一条出错信息,然后通过调用abort来终止程序运行。请看下面的程序实例:
#include "stdafx.h"
#include <stdio.h>
#include <assert.h>
using namespace std;
#pragma warning(disable:4996);
int main(void)
{
FILE *fp;
fp = fopen("F:/test.txt", "w"); //以可写的方式打开一个文件,如果不存在就创建一个同名文件
assert(fp); //所以这里不会出错
fclose(fp);
fp = fopen("F:/noexitfile.txt", "r"); //以只读的方式打开一个文件,如果不存在就打开文件失败
assert(fp); //所以这里出错
fclose(fp); //程序永远都不会执行到这一步
getchar();
return 0;
}
运行结果:
二、使用
1、在函数体的“入口处”,对参数的有效性进行检查。很多程序错误是由非法参数引起的,我们应该充分理解并正确使用“断言”(assert)来防止此类错误。
2、在调试结束后,可以通过在包含#include<assert.h>的语句之前插入#define NDEBUG来禁用assert调用,实例代码如下:
#include "stdafx.h"
#include <stdio.h>
#define NDEBUG
#include <assert.h>
3、每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败,如:
//不良写法
assert(nOffset >= 0 && nOffset + nSize <= m_nInformationSize);
//良好写法
assert(nOffset >= 0);
assert(nOffset + nSize <= m_nInformationSize);
4、不能使用改变环境的语句,因为assert只在DEBUG中生效,如果这么做,会使应用程序在真正运行时遇到问题,如:
//错误:
assert(i++ < 100);
这是因为如果出错,比如在执行之前i = 100,那么i++这条命令就不会执行。
//正确:
assert(i < 100);
i++;
5、assert和后面的语句应该空一行,以形成逻辑和视觉上的一致感。
6、有的地方,assert不能代替条件过滤。assert是用来避免显而易见的错误的,而不是处理异常的,错误和异常是不一样的,错误是不应该出现的,异常是不可避免的。C语言异常可以通过条件判断来处理,其他语言有各自的异常处理机制。
2015年5月26日