assert.h,头文件assert.h什么意思
本篇文章给大家谈谈assert.h,以及头文件assert.h什么意思对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。
C语言中assert断言的用法
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行。
库函数: assert.h
原型定义: void assert( int expression);
assert的作用是现计算表达式 expression,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort来终止程序运行。
例程:
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
int main( void)
{
FILE*fp;
fp= fopen("test.txt","w");//以可写的方式打开一个文件,如果不存在就创建一个同名文件
assert( fp);//所以这里不会出错
fclose( fp);
fp= fopen("noexitfile.txt","r");//以只读的方式打开一个文件,如果不存在就打开文件失败
assert( fp);//所以这里出错
fclose( fp);//程序永远都执行不到这里来
return 0;
}
[root@localhost error_process]# gcc badptr.c
[root@localhost error_process]#./a.out
a.out: badptr.c:14: main: Assertion `fp'' failed.
已放弃
使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
在调试结束后,可以通过在包含#include<assert.h>的语句之前插入#define NDEBUG来禁用assert调用,示例代码如下:
#include<stdio.h>
#define NDEBUG
#include<assert.h>
用法总结与注意事项:
1)在函数开始处检验传入参数的合法性
如:
int resetBufferSize(int nNewSize)
{
//功能:改变缓冲区大小,
//参数:nNewSize缓冲区新长度
//返回值:缓冲区当前长度
//说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区
assert(nNewSize>= 0);
assert(nNewSize<= MAX_BUFFER_SIZE);
...
}
2)每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
不好: assert(nOffset>=0&& nOffset+nSize<=m_nInfomationSize);
好: assert(nOffset>= 0);
assert(nOffset+nSize<= m_nInfomationSize);
3)不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
错误: assert(i++< 100)
这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i++这条命令就没有执行。
正确: assert(i< 100)
i++;
4)assert和后面的语句应空一行,以形成逻辑和视觉上的一致感
5)有的地方,assert不能代替条件过滤
头文件assert.h什么意思
这是c语言的一个库,如果你在编程中用到这个库里面的东西,你需要引用这个库。
头文件<assert.h>唯一的目的就是提供assert宏定义,可以在程序中关键的地方使用这个宏来进行断言。如果一处断言被证明非真,希望程序在标准错误流输出一条适当的提示信息,并使执行异常终止。
百度上一搜索一堆,你去学习学习~
assert.h 是什么的头文件
assert.h常用于防御式编程。断言(Assertions),一个断言通常是一个例程(routines)或者一个宏(marcos)。每个断言通常含有两个参数:一个布尔表示式(a boolean expression)和一个消息(a message)。
assert.hassert.h常用于防御式编程。
[1]断言(Assertions)
一个断言通常是一个例程(routines)或者一个宏(marcos)。每个断言通常含有两个参数:一个布尔表示式(a boolean expression)和一个消息(a message)。一个布尔表达式的反面表示了一个错误。C标准库提供了一个 assert宏,它只带有一个参数,用法如下:
assert(1== 0);//注意 boolean expression不要加引号
使用 assert宏,需要包含头文件 cassert或者 assert.h,执行上面语句的结果是程序终止运行,输出与下面消息类似的消息:
Assertion failed: 1== 0, file d:\我的文档\visual studio projects\learning\assert\assert.cpp, line 9
通常来说,我们会定义自己的 assert宏,其目的有两个:
(1)新增参数,例如新增一个消息参数,使得 assert宏输出更为丰富的信息。
(2)改变 assert的行为内容。C标准库中的 assert宏将中断程序,实际上,我们可以让程序继续运行而不中断或者进入调试状态等,另外还可以控制消息输出的目标,即控制消息是输出到控制台还是文本文件,甚至是通过网络发出。
下面是一个 C++实现的断言:
#ifdef _DEBUG
#define Assert(exp, message)\
{\
if(!(exp))\
{\
std::cout<<"Assertion failed:"<<#exp<<"\n"\
<<"Message:"<< message<<"\n"\
<<"line:"<< __LINE__<<"\n"\
<<"file:"<< __FILE__<<"\n";\
exit(EXIT_FAILURE);\
}\
}
#else
#define Assert(exp, message)
#endif
执行 Assert(1== 0,"Error");结果为:
Assertion failed: 1== 0
Message: Error
line: 24
file: d:\我的文档\visual studio projects\learning\assert\assert.cpp
使用断言应该注意一下的几个问题:
1)对非预期错误使用断言
断言中的布尔表达式的反面一定要描述一个非预期错误,下面所述的在一定情况下为非预期错误的一些例子:
(1)空指针。
(2)输入或者输出参数的值不在预期范围内。
(3)数组的越界。
非预期错误对应的就是预期错误,我们通常使用错误处理代码来处理预期错误,而使用断言处理非预期错误。在代码执行过程中,有些错误永远不应该发生,这样的错误是非预期错误。断言可以被看成是一种可执行的注释,你不能依赖它来让代码正常工作。例如:在
int nRes= f();// nRes由 f函数控制, f函数保证返回值一定在-100~ 100
Assert(-100<= nRes&& nRes<= 100);//断言,一个可执行的注释
由于 f函数保证了返回值处于-100~ 100,那么如果出现了 nRes不在这个范围的值时,就表明一个非预期错误的出现。后面会讲到“隔栏”,那时会对断言有更加深刻的理解。
2)不要把需要执行的代码放入断言中
断言用于软件的开发和维护,而通常不在发行版本中包含断言。
需要执行的代码放入断言中是不正确的,因为在发行版本中,这些代码通常不会被执行,例如:
Assert(f());// f函数通常在发行版本中不会被执行
而使用如下方法则比较安全:
res= f();
Assert(res);//安全
3)对来源于内部系统的可靠的数据使用断言,而不要对外部不可靠的数据使用断言,对于外部不可靠数据,应该使用错误处理代码。再次强调,把断言看成可执行的注释。
前条件(preconditions)和后条件(postconditions)
前条件是调用方代码在调用例程(routines)或者实例化对象之前要确保为真的条件,后条件是例程执行后或者类实例化后应满足的条件。下面是一个例子:
//前条件,这里 nNum1和 nNum2的取值被前面代码所约束并保证取值在-50~ 50
Assert(-50<= nNum1&& nNum1<= 50,"Add_nNum1");
Assert(-50<= nNum2&& nNum2<= 50,"Add_nNum2");
int nRes= add(nNum1, nNum2);
//后条件
Assert(-100<= nRes&& nRes<= 100,"Add_nRes");
注意,由于 nNum1和 nNum2取值范围已经被约束,因此可以使用断言,但是如果 nNum1和 nNum2的值来源于不可靠的外部系统,那么应该使用错误处理代码,而不是使用断言。
END,本文到此结束,如果可以帮助到大家,还望关注本站哦!