Chinaunix首页 | 论坛 | 博客
  • 博客访问: 35050
  • 博文数量: 9
  • 博客积分: 156
  • 博客等级: 入伍新兵
  • 技术积分: 60
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-22 16:36
文章分类
文章存档

2014年(1)

2012年(3)

2011年(5)

我的朋友
最近访客

分类: C/C++

2011-10-21 22:35:32

用法:

先包含
#inlcude

在想用的地方给一句:
assert(expression)就可以了。
expression是任意有效的逻辑表达式。
比如:

FILE *fp = fopen("in.txt","r") ;
if ( ! fp ){
exit(0) ;
}
assert(fp != NULL) ;

当expression不满足时,就会报出一个很丑陋的框框,
然后向控制台输出assert不满足的文件和行号。

具体到debug的时候,
可以撒网式地在各个地方放上认为应该为真的表达式的assert,
说不定哪个就爆了,于是趁机发现了问题。

原理:

只要有源码就没有秘密,
所以打开assert.h,看看里面是怎么写的。

主要的就这两句:
_CRTIMP void __cdecl _assert(void *, void *, unsigned);
#define assert(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) )

第一句就干的就是输出一些信息,然后弹出个框框,
顺便结束程序这些勾当。
他被调用的时候,是类似于:
_assert("false" , "c:\\1.cpp" , 15)
这样。

第二句的构造可谓精简啊,小小一句话还包含了挺多以前没注意到的事情。

1.短路求值

这个是c的重要特性,在处理&&的时候前面为假则不用继续,
在处理|| 的时候,前面为真则不用继续。
形象地说把后面的表达式短路了。

2.单行宏

#exp 生成"exp"这样的字符串
#@a 生成'a'这样的字符
a##b 把a和b连接起来

第一个用法在这里见到了,第二个暂时还没见到用的实例。
第三个在a和b是宏的参数的时候有用。否则直接的ab会被当作一个东西。

3.特殊的预定义宏

__FILE__ 会被替换成所在的文件,字符串形式
__LINE__ 会被替换成行号,unsigned类型
__DATE__ 会被替换成日期
__TIME__ 会被替换成时间

其实之前翻过的跟C有关的书应该都讲了这些的。
不过拿着一个列表,又不给出真正实用的例子,
当然不知道这些东西是怎么回事,
久了自然也就忘了。

4.逗号表达式

感觉实在是一个用的很少的事情,
毕竟有多句话的时候,完全可以用分号就行了。
虽然有好多地方在if之类的里面很压缩的用逗号表达式写好几句话,
其实都可以改得不用逗号表达式的。

其一是逗号表达式的优先级很低,所以后面那对括号实在是不可缺少。

其二是逗号表达式的值为最右边式子的值。
这个估计很多人都记过,但不见得有啥重大意义。
这里,倒确实是发挥了他的意义。
因为_asert这个函数是void型的,
如果不使用逗号表达式在右边补个0的话,
会报告:(VC6)
error C2297: '||' : illegal, right operand has type 'void'

改编:

知道是怎么回事,当然可以很容易做出自己想要的东西。
再说还有asert.h里面的参照呢。

比如,我嫌默认的_assert弹出的东西看着太压抑了。。。
就自己写个就行了。

#include
#include
#include

#define MAX_BUFFER 200
void _assert(char *msg , char *file , unsigned line){
char buf[MAX_BUFFER] ;
sprintf(buf , "assertion fail:\n%s\nin file:\n%s\non line:\n%d" , msg , file , line) ;
::MessageBox(NULL , buf , "assertion failure" , MB_OK) ;
exit(0) ;
}

#define assert(exp) ((exp) || (_assert(#exp , __FILE__ , __LINE__) , 0) )

int main(){
assert(1 == 1 && 3 == 4) ;
return 0 ;
}

至于我的这个是不是更压抑。。那不属于这里讨论的问题了。

反正通过简单变更_assert函数,可以把相关情况输出到文件,
或者选择另外的方式表达出来,能想到的都可以。

至于assert这个宏,也有可以动手脚的地方。
自带的是assert一个为真的表达式。
有的时候就想assert一个为假的表达式,当他为真的时候发出警告。

比如:

FILE *fp = fopen("in.txt","r") ;
if ( ! fp ){
exit(0) ;
}
warn(fp == NULL)

套用上面的写法,既然是为真发警告,那么用&&去换||就行了。
阅读(1332) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~