C++问题。define ndebugG到底有什么用,C++prime 5th上说用它,assert就没用了。为什

assert俗称断言,个人认为称有校性校验更准确,这里是它的用法,亲测通过
#include &iostream&
#include &assert.h&
// #define _NDEBUG
#ifndef _NDEBUG
#define _DEBUG
#endif // _DEBUG
bool TestValue(int a)
if ( a & 100 )
int main()
int x = 10;
#ifdef _DEBUG
assert( TestValue(x) );
cout && &Hello world!& &&
assert( TestValue(x) );
cout && &New Hello World!& &&
#ifdef _DEBUG
assert( TestValue(x) );
cout && &The last line output!!!& &&
#include &iostream&
#include &assert.h&
// #define _NDEBUG
#ifndef _NDEBUG
#define _DEBUG
#endif // _DEBUG
bool TestValue(int a)
if ( a & 100 )
int main()
int x = 10;
#ifdef _DEBUG
assert( TestValue(x) );
cout && &Hello world!& &&
assert( TestValue(x) );
cout && &New Hello World!& &&
#ifdef _DEBUG
assert( TestValue(x) );
cout && &The last line output!!!& &&
// 整体上很简单,思路也比较清楚了,不必做注释,复制下来跑一遍就啥都明白了。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'关于assert与if语句的使用
[问题点数:40分,结帖人shexinwei]
关于assert与if语句的使用
[问题点数:40分,结帖人shexinwei]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2013年5月 高性能开发大版内专家分月排行榜第二2013年4月 高性能开发大版内专家分月排行榜第二
2013年3月 C/C++大版内专家分月排行榜第三
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年3月 C/C++大版内专家分月排行榜第三
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
本帖子已过去太久远了,不再提供回复功能。34006人阅读
assert宏的原型定义在&assert.h&中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:
#include&&assert.h&
void&assert(&int&expression&);
assert的作用是现计算表达式&expression&,如果其值为假(即为0),那么它先向stderr打印一条出错信息,
然后通过调用&abort&来终止程序运行。
请看下面的程序清单badptr.c:
#include&&stdio.h&
#include&&assert.h&
#include&&stdlib.h&
int&main(&void&)
&&&&&&&FILE&*
&&&&&&&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&
用法总结与注意事项:
<span style="color:#)在函数开始处检验传入参数的合法性
int&resetBufferSize(int&nNewSize)
//功能:改变缓冲区大小,
//参数:nNewSize&缓冲区新长度
//返回&#20540;:缓冲区当前长度&
//说明:保持原信息内容不变&&&&&nNewSize&=0表示清除缓冲区
assert(nNewSize&&=&0);
assert(nNewSize&&=&MAX_BUFFER_SIZE);
<span style="color:#)每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
不好:&assert(nOffset&=0&&&&nOffset&#43;nSize&=m_nInfomationSize);
好:&assert(nOffset&&=&0);
assert(nOffset&#43;nSize&&=&m_nInfomationSize);
<span style="color:#)不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
错误:&assert(i&#43;&#43;&&&100)
这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i&#43;&#43;这条命令就没有执行。
正确:&assert(i&&&100)
&&&&&&&&&i&#43;&#43;;
&&&&&&&&&&&&
<span style="color:#)assert和后面的语句应空一行,以形成逻辑和视觉上的一致感
<span style="color:#)有的地方,assert不能代替条件过滤
文章出处:
摘自《高质量C/C&#43;&#43;编程指南》Page&41-42...
程序一般分为Debug&版本和Release&版本,Debug&版本用于内部调试,Release&版本发行给用户使用。
断言assert&是仅在Debug&版本起作用的宏,它用于检查不应该发生的情况。示例6-5&是一个内存复制函数。在运行过程中,如果assert&的参数为假,那么程序就会中止(一般地还会出现提示对话,说明在什么地方引发了assert)。
void&*memcpy(void&*pvTo,&const&void&*pvFrom,&size_t&size)
&&&&assert((pvTo&!=&NULL)&&&&(pvFrom&!=&NULL));&//&使用断言
&&&&byte&*pbTo&=&(byte&*)&pvTo;&//&防止改变pvTo&的地址
&&&&byte&*pbFrom&=&(byte&*)&pvF&//&防止改变pvFrom&的地址
&&&&while(size&--&&&0)
&&&&&&&&*pbTo&&#43;&#43;&=&*pbFrom&&#43;&#43;&;
&&&&return&pvTo;
示例6-5&复制不重叠的内存块
assert&不是一个仓促拼凑起来的宏。为了不在程序的Debug&版本和Release&版本引起差别,assert&不应该产生任何副作用。所以assert&不是函数,而是宏。程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。如果程序在&assert&处终止了,并不是说含有该assert&的函数有错误,而是调用者出了差错,assert&可以帮助我们找到发生错误的原因。
很少有比跟踪到程序的断言,却不知道该断言的作用更让人沮丧的事了。你化了很多时间,不是为了排除错误,而只是为了弄清楚这个错误到底是什么。有的时候,程序员偶尔还会设计出有错误的断言。所以如果搞不清楚断言检查的是什么,就很难判断错误是出现在程序中,还是出现在断言中。幸运的是这个问题很好解决,只要加上清晰的注释即可。这本是显而易见的事情,可是很少有程序员这样做。这好比一个人在森林里,看到树上钉着一块危险的大牌子。但危险到底是什么?树要倒?有废井?有野兽?除非告诉人们危险是什么,否则这个警告牌难以起到积极有效的作用。难以理解的断言常常被程序员忽略,甚至被删除。
【规则6-5-1】使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。
【规则6-5-2】在函数的入口处,使用断言检查参数的有效性(合法性)。
【建议6-5-1】在编写函数时,要进行反复的考查,并且自问:我打算做哪些假定?一旦确定了的假定,就要使用断言对假定进行检查。
【建议6-5-2】一般教科书都鼓励程序员们进行防错设计,但要记住这种编程风&#26684;可能会隐瞒错误。当进行防错设计时,如果不可能发生的事情的确发生了,则要使用断言进行报警。
ASSERT宏中应该包含的元素:
判断条件;输出当前断言失败的位置(文件、行数等);返回错误;终止程序...
几种典型的ASSERT的写法:
VC中的写法:
#define&ASSERT(f)&\
&&&if&(!(f)&&&&AfxAssertFailedLine(THIS_FILE,&__LINE__))&\
&&&AfxDebugBreak();&\
}&while&(0)&\
#define&_ASSERT(expr)&\
&&&&&&&&do&{&if&(!(expr)&&&&\
&&&&&&&&&&&&&&&&(1&==&_CrtDbgReport(_CRT_ASSERT,&__FILE__,&__LINE__,&NULL,&NULL)))&\
&&&&&&&&&&&&&_CrtDbgBreak();&}&while&(0)
其他平台的写法:
#&define&ASSERT(x)&((x)&||&(dbg_printf(&assertion&failed&(&__FILE__&:%d):&\&%s\&\n&,__LINE__,#x),&break_point(),&FALSE))
原网站地址:/uwbadnhctpkopwr/item/1d5d1e1d316c79fcdceeca0a
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:149707次
积分:1757
积分:1757
排名:第17048名
原创:37篇
转载:53篇
评论:18条
(3)(3)(1)(1)(7)(14)(24)(37)C/C++(185)
MSDN原文如是说:
Evaluates an expression and, when the result is&false, prints a diagnostic message and aborts the program.
(判断一个表达式,如果结果为假,输出诊断消息并中止程序。)
参数:Expression (including pointers) that evaluates to nonzero or 0.(表达式【包括指针】是非零或零)
原理:assert的作用是现计算表达式 expression ,如果其&#20540;为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
MSDN示例程序;
用法总结:
1)在函数开始处检验传入参数的合法性
int resetBufferSize(int nNewSize)
& //功能:改变缓冲区大小,
& //参数:nNewSize 缓冲区新长度
//返回&#20540;:缓冲区当前长度
//说明:保持原信息内容不变&&&& nNewSize&=0表示清除缓冲区
assert(nNewSize &= 0);
assert(nNewSize &= MAX_BUFFER_SIZE);
2)每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
不好:&assert(nOffset&=0 && nOffset&#43;nSize&=m_nInfomationSize);
好:&assert(nOffset &= 0);
&&&& assert(nOffset&#43;nSize &= m_nInfomationSize);
3)不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
错误:&assert(i&#43;&#43; & 100)
这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i&#43;&#43;这条命令就没有执行。
正确:&assert(i & 100);
&&&&&&&& i&#43;&#43;;
4)assert和后面的语句应空一行,以形成逻辑和视觉上的一致感
5)有的地方,assert不能代替条件过滤
ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略掉。(在C中,ASSERT是宏而不是函数),使用ASSERT“断言”容易在debug时输出程序错误所在。
&& 而assert()的功能类&#20284;,它是ANSI C标准中规定的函数,它与ASSERT的一个重要区别是可以用在Release版本中。
使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
在调试结束后,可以通过在包含#include &assert.h&的语句之前插入 #define NDEBUG 来禁用assert调用,示例代码如下:
#include &stdio.h&
#define NDEBUG
#include &assert.h&
加入#define NDEBUG之后,上文第一个例子输出结果为:
在面试中经常用到的一个题目:
已知memcpy的函数为: void* memcpy(void *dest , const void* src , size_t count)其中dest是目的指针,src是源指针。不调用c&#43;&#43;/c的memcpy库函数,请编写memcpy。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:366104次
积分:5146
积分:5146
排名:第3834名
原创:70篇
转载:618篇
评论:16条
(13)(18)(41)(21)(6)(3)(22)(29)(22)(35)(46)(9)(15)(19)(22)(87)(11)(22)(17)(14)(2)(12)(1)(6)(16)(49)(34)(27)(29)(11)(24)(10)(2)下次自动登录
现在的位置:
& 综合 & 正文
[C++]NDEBUG宏与assert行为
NDEBUG宏是Standard C中定义的宏,专门用来控制assert()的行为。如果定义了这个宏,则assert不会起作用。
#ifdef NDEBUG#define assert(x) ((void)0)#else...
C Standard中规定了assert以宏来实现。&assert.h&被设计来可以被多次包含,其中一上来就undef assert,然后由NDEBUG宏来决定其行为。如:
#ifdef NDEBUG
#undef NDEBUG
#include &assert.h&
#define NDEBUG#else
#include &assert.h&#endif // #ifdef NDEBUG
将以上放在c/cpp最上方(当然,其后不能出现其它#include &assert.h&语句),就可以保证c/cpp所在的编译单元中的assert,在release下也会触发abort行为。
NDEBUG宏由于字面意思,也被用于作为判断debug/release版本的宏,不过这个是编译器、环境相关的,并不可靠。
比如vc中,对生成的release版本项目,默认会定义这个宏,而gcc并没有定义,得用-DNDEBUG参数来定义。
C++ Standard中完全采用了C中的定义。
C - Approved standards
C++ Standard(ISO/IEC 14882)
&&&&推荐文章:
【上篇】【下篇】

我要回帖

更多关于 assert 的文章

 

随机推荐