c.k:C++

assert宏定义在<assert.h>,如下示例:

#if defined NDEBUG
#define assert(condition) ((void) 0)
#else
#define assert(condition) _assert((condition), #condition, __FILE__, __LINE__)
#endif (译注:assert的实现并不唯一,比如:

Visual C++ 6.0的实现是:

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

Borland C++ 5.5的实现是:

#define assert(exp) ((exp) ? (void)0 : _assert(#exp, __FILE__, __LINE__))

  至于函数_assert(在gcc的库中_assert是一个宏)是各家的内部实现,不一定得非要_assert这个名字,其内容一般是利用printf函数(在WIN平台上往往是调用MessageBox)输出出错信息(文件名及行号)并调用abort终止程序。

  //*******************************************************//

  在这个定义里,当定义了预处理符号NDEBUG的时候,断言是无效的,这意味着assert断言宏只在你的Debug版本中有效。在Release版本里,assert断言宏不进行任何计算。由于这个而会引起一些侧面效里,比如:

/* debug version */
#undef NDEBUG
#include <assert.h>
#include <stdio.h>

int main(void)
{
int i = 0;
assert(++i != 0);
printf("i is %d\n", i);
return 0;
}
/* 当运行后输出:

i is 1
*/
那么现在改变代码版本到release版本,定义NDEBUG:

/* release version */
#defing NDEBUG
#include <assert.h>
#include <stdio.h>

int main(void)
{
int i = 0;
assert(++i != 0);
printf("i is %d\n", i);
return 0;
}

/* 当运行后输出:

i is 0
*/

  因此在assert中只能是比较而不能有实质性的动作,否则调试和发布版的结果可能会大相径庭。

  因此,为了避免这种差异,确保在assert表达式不能包含有侧面影响的代码。

  (译注:切记assert中不能存在任何实质性的动作。Microsoft提供了ASSERT和VERIFY等等宏,其中VERIFY可以用在发布版内,不过这既非C/C++标准,功能亦不够强大。)

  只在Debug版本里,assert会调用_assert函数。以下是相似代码:

void _assert(int test, char const *test_image,
char const *file, int line)
{
if (!test)
{
printf("Assertion failed: %s, file %s, line %d\n",
test_image, file, line);
[ft=,,] a
Tags:  大c c语言 6120c c.k

延伸阅读

最新评论

发表评论