assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,我们常常这样使用assert宏:
void main()
{
int* p = NULL;
p = (int *)malloc(sizeof(int));
assert(p != NULL);
...
}
如果让我来定义assert宏,我可能会定义成如下的形式:
#define assert(exp) if(!exp) _assert(#exp, __FILE__, __LINE__)
上面的宏使用的是语句,在某些情形下,这个宏有一些难以察觉的错误,假如我们有如下的宏调用:
if(x > 0)
assert(y > x);
else
assert(x > y);
...
我们把宏展开:
if(x > 0)
if(!(y > x))) _assert("y > x", __FILE__, __LINE__);
else
if(!(x > y)) _assert(" x > y", __FILE__, __LINE__);
...
由于else默认是跟离它最近的if匹配,我们重新缩进下:
if(x > 0)
if(!(y > x))) _assert("y > x", __FILE__, __LINE__);
else
if(!(x > y)) _assert(" x > y", __FILE__, __LINE__);
...
这和我们想要的结果是不同的,
我们再来看看系统如何定义assert宏:
#define assert(exp) (void)((exp) || (_assert(#exp, __FILE__, __LINE__), 0))
这个宏是一个表达式,不是语句,利用了||语句的短路现象,||前面的表达式为真时,后面的不再计算,当||之前为假时,才处理后面的表达式;
宏中有个#exp,这里的#号是提取exp的值;
表达式最后有一个0处于逗号运算符之后,这样处理确保整个表达式最后值为0,即为false。
|