定义一个即使定义了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
复制它。