定义一个即使定义了NDEBUG也有效的断言

我想定义一个assert宏,它与标准的assert(3)调用相同,只是在定义NDEBUG时预处理器不会删除它。

这样的调用,让我们在这里称之为assert2 ,例如,如果你想在软件的发布版本中进行一些检查,那么它是有用的。

我怎样才能以合理的便携方式做到这一点? 我总是可以完全重新创建assert机制,如1

 #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调用做了很好的事情,比如处理编译器和平台的所有各种奇怪的东西,用特殊的魔法注释断言条件,让编译器在调用后假设条件成立,相当打印函数名称,等等上。

在包含assert.h之前,我可以通过#undef NDEBUG获取内置assert – 但是我看不到如何将它重命名为assert2 。 我想我可以将系统头文件中assert定义复制并粘贴到#define assert2行,但这是(a)可能违反某些许可或版权,(b)需要重复平台。

请不要开始辩论这种function是否有用,或者它是否是实现更高级别目标的合理方式。 我特别询问是否可以在不依赖于NDEBUG情况下以其他名称重用现有的assert调用。


1当然,将die_now声明为static函数并不理想,因为它将在每个使用as assert编译单元中复制die_now函数(或者更糟糕的是,甚至可能包括所有那些仅包含头部的那些),因此它应该真正定义在它自己的并发单元中脱节,但这是使用这个function的另一个复杂因素。

assert2这样做:永远不要定义NDEBUG ,因此始终启用assert ,并定义一个assert2 ,它是一个无操作或assert的别名。 然后你可以assert2打开和关闭assert2

文件assert2.h

 // Note: no include guard // // Copy NDEBUG to NDEBUG2 #undef NDEBUG2 #ifdef NDEBUG #define NDEBUG2 1 #endif #undef NDEBUG /* include , 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  /* Now define an assert which respects the original NDEBUG */ #undef assert2 #ifdef NDEBUG2 #define assert2(x) #else #define assert2 assert #endif 

现在,您可以在定义或取消定义NDEBUG之后重新包含"assert2.h"来回翻转。 上面的文件总是NDEBUG2定义NDEBUG作为副作用,但你最后可以从NDEBUG2复制它。