在C语言的库函数中,提供了一个辅助调试程序的小库,由assert()宏组成。本文详细介绍了如何使用,有兴趣的可以看看。
在C语言库函数中,提供了一个辅助调试程序的小库,由assert()宏组成,接受一个整形表达式作为参数。如果表达式的值为false(非零),assert()宏将在标准错误流(stderr)中写入一条错误消息,并调用abort()函数来终止程序。
让我们通过一个简单的例子来看看assert()的用法。
int main()
{
int n=1;
断言(n=0);
printf('%d \r\n ',n);
系统(“暂停”);
返回0;
}
在assert()中,表达式判断的条件是n ^ 0,所以当整形变量n的值小于0时,表示表达式为假,断言函数就会起作用。这里先试试正常情况,将n的值设为1,输出结果如下:
接下来,将n的值改为-1,继续测试。
此时,程序异常终止。下面详细分析一下这个函数的执行过程。
在assert.h的头文件中可以看到assert()的原型,这里有两个原型。一个是定义了_UNICODE或者UNICODE时调用第一个assert(),没有定义时调用第二个assert()。因为头文件中没有定义_UNICODE或UNICODE,所以这里调用了第二个assert。我们来分析一下这个宏定义语句。
# define assert(_ Expression)(void)((!(_ Expression))| |(_ assert(# _ Expression,__FILE__,__LINE__),0))
void _ _ cdecl _ assert(const char * _ Message,const char *_File,unsigned _ Line);
首先,将一个parameter _Expression传入assert,然后是一个由OR运算符连接的两部分组成的语句。对于or运算符||,当第一个条件为真时,不会执行第二个条件,只有当第一个条件为假时,才会执行第二条语句。
((!(_ Expression))| |(_ assert(# _ Expression,__FILE__,__LINE__),0))
首先看第一个判断条件(!!(_Expression))。传入的参数被求反两次,相当于变量本身。当_Expression为true时,不会执行第二个条件。只有当_Expression为false时,才会执行第二个条件。在程序中,当n 0成立时,不会执行第二个条件,当n 0不成立时,会执行第二条语句。所以在上面的测试中,当n=-1时程序会异常终止。
接下来看第二个条件(_assert(#_Expression,FILE,LINE),0)这是一个函数,它的原型是:
void _ _ cdecl _ assert(const char * _ Message,const char *_File,unsigned _ Line);
这个函数有三个参数。根据这三个参数的名称,可以推断出第一个参数用来存储信息内容,第二个参数用来表示当前文件的细节,第三个参数表示代码中哪一行错了。
这三个参数与控制台打印的内容一致。Program后面是当前运行的可执行文件的路径,File后面是错误报告文件的路径,Line后面是错误的具体位置,这表明test6.c文件中第16行的程序有错误。最后一行表示错误表达式为n=0,表示变量n大于等于0的条件不成立,即当前变量n的值小于0,从而引起程序异常。
从上面的分析可以看出,assert()对于调试程序是很有帮助的。编译程序时,编译器无法检测出像这样隐藏在代码中的错误,只能在程序执行时发现。所以通过assert()检测表达式可以快速定位程序的bug。
我不想用assert()来检测。我不需要修改代码。我只需要在assert.h中定义NDEBUG
在assert.h中添加宏定义,继续运行程序。
此时n的值为-1,但程序正常打印出-1,没有报错。解释assert()不检测错误。这一点从头文件中也可以看出来。
定义NDEBUG时,**assert(_Expression)**执行的具体函数变成((void)0),也就是什么都不做。所以在头文件中定义NDEBUG时,assert()的检测函数会自动失效。这样,在调试程序时,只需要一条语句就可以打开或关闭调试信息输出。
关于C语言断言函数assert()的学习笔记这篇文章到此为止。有关C语言中断言函数assert()的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望大家以后能多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。