定义一个有效的断言

定义一个有效的断言

本文介绍了定义一个有效的断言,即使定义了NDEBUG的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想定义一个assert宏,它与标准 assert(3) 调用,只是定义了NDEBUG时预处理器不会将其删除.

I would like to define an assert macro which is identical to the standard assert(3) call except that it isn't removed by the pre-processor when NDEBUG is defined.

例如,如果您还希望在软件的发行版本中进行一些检查,那么这样的调用(在这里我们称为assert2)很有用.

Such a call, let us call it assert2 here, is useful for example if you want to have some checks happen in release versions of software as well.

我该如何以合理的便携式方式执行此操作?我总是可以完全重新创建assert机制,例如:

How can I do this in a reasonably portable way? I could always just completely re-create the assert mechanism, like:

#define assert2(cond) cond ? (void)0 : die_now(#cond, __FILE__, __LINE__)

static die_now(char *cond_str, const char *file, int line) {
  // print a message to stderr here
  ...
  abort();  // or maybe abort ?
}

...但是我更愿意使用与现有断言调用相同的机制.特别是,内置的assert调用可以完成很多不错的工作,例如处理编译器和平台的所有各种怪异现象,并通过特殊的魔术符注释断言条件,从而使编译器假定该条件在调用后成立,并打印出漂亮的函数名称,等等.

... but I'd much rather just use the same mechanism as the existing assert call. In particular, the built-in assert call does nice stuff like handling all the various weirdnesses of your compiler and platform, annotating the assert condition with special magic that lets the compiler assume the condition holds after the call, pretty printing function names, and so on.

在包含assert.h之前,我可以通过#undef NDEBUG获得内置的assert-但我看不到如何将其重命名为assert2.我想我可以求助于&将系统头文件中assert definition 粘贴到#define assert2行中,但这是(a)可能违反某些许可证或版权,并且(b)需要重复以下操作:每个平台.

I could get the builtin assert by just #undef NDEBUG before including assert.h - but I can't see how to rename it to assert2. I guess I could resort to copy & pasting the definition of assert in the system header files into the #define assert2 line, but this is (a) a possible violation of some license or copyright and (b) would need to be repeated for each platform.

请不要争论这种功能是否有用,或者它是否是实现更高层次目标的合理方法.我专门问我是否可以在不依赖NDEBUG的情况下以另一个名称重用现有的assert调用.

Please don't start a debate whether such a function is useful or not, or whether it's a reasonable way to accomplish a higher-level aim. I am asking specifically whether I can re-use the existing assert call, under another name, without the dependence on NDEBUG.

当然,将die_now声明为static函数并不理想,因为它将在每个用作assert的编译单元中复制die_now函数(或更糟糕的是, ,甚至可能只包含标头的所有内容都可以),因此应确实在其自己的复杂单元中对它进行脱机定义,但这是使用此函数的另一复杂情况.

Of course, declaring die_now as a static function isn't ideal since it will duplicate the die_now function in every compilation unit that uses as assert (or worse, perhaps even all those that just include the header), so it should really be defined out-of-line in its own complication unit, but that's another complication to the use of this function.

推荐答案

我将采用另一种方法:永远不要定义NDEBUG,因此始终启用assert,并定义assert2无操作或assert的别名.然后,您可以根据需要打开和关闭assert2:

I'd do this the other way around: never define NDEBUG, so assert is always enabled, and define an assert2 which is either a no-op or an alias of assert. Then you can turn assert2 on and off at your pleasure:

// Note: no include guard
//
// Copy NDEBUG to NDEBUG2
#undef NDEBUG2
#ifdef NDEBUG
#define NDEBUG2 1
#endif
#undef NDEBUG
/* include <assert.h>, so that assert and friends are defined
 * assert.h also lacks an include guard, but multiple inclusions
 * are required to be OK (section 7.1.2 paragraph 4, if you care.)
 */
#include <assert.h>
/* Now define an assert which respects the original NDEBUG */
#undef assert2
#ifdef NDEBUG2
#define assert2(x)
#else
#define assert2 assert
#endif

现在,您可以在定义或取消定义NDEBUG之后通过包含"assert2.h"来回切换.上面的文件始终未将NDEBUG定义为副作用,但是您可以最后从NDEBUG2复制回去.

Now you can flip back and forth by reincluding "assert2.h" after defining or undefining NDEBUG. The above file always undefines NDEBUG as a side-effect, but you could copy it back from NDEBUG2 at the end.

这篇关于定义一个有效的断言,即使定义了NDEBUG的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 18:56