gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 02:31:58 27 4
gpt4 key购买 nike

我想定义一个与标准 assert(3) 相同的 assert 宏除了在定义 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 调用可以做一些很好的事情,比如处理编译器和平台的所有各种怪异情况,用特殊的魔法注释断言条件,让编译器假设条件在调用后成立, pretty-print 函数名称,等等。

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

请不要开始争论这样的功能是否有用,或者它是否是实现更高层次目标的合理方法。我特别询问是否可以在不依赖 NDEBUG 的情况下以另一个名称重新使用现有的 assert 调用。


1 当然,将 die_now 声明为 static 函数并不理想,因为它会复制 die_now 在每个使用 as assert 的编译单元中运行(或者更糟,甚至可能是所有只包含 header 的编译单元),因此它实际上应该在其自己的复杂单元中定义为外联,但是这是使用此功能的另一个复杂因素。

最佳答案

我会以相反的方式来做:从不定义 NDEBUG,所以 assert 总是启用的,并定义一个 assert2 这是assert 的空操作或别名。然后您可以随意打开和关闭 assert2:

文件assert2.h

// 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 将它复制回来。

关于c - 定义一个即使定义了 NDEBUG 也有效的断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42093734/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com