为啥在发布版本中断言宏的定义不能只是`#define assert(expression) 0`?
Posted
技术标签:
【中文标题】为啥在发布版本中断言宏的定义不能只是`#define assert(expression) 0`?【英文标题】:Why the definition of the assert macro, in a release build, cannot be just `#define assert(expression) 0`?为什么在发布版本中断言宏的定义不能只是`#define assert(expression) 0`? 【发布时间】:2020-05-09 18:18:14 【问题描述】:这是 Visual Studio 2019 中断言宏的定义
#ifdef NDEBUG
#define assert(expression) ((void)0)
#else
_ACRTIMP void __cdecl _wassert(
_In_z_ wchar_t const* _Message,
_In_z_ wchar_t const* _File,
_In_ unsigned _Line
);
#define assert(expression) (void)( \
(!!(expression)) || \
(_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
)
#endif
正如你在上面看到的,在发布版本中宏断言的定义是
#define assert(expression) ((void)0)
为什么不能只是#define assert(expression) 0
?
【问题讨论】:
相关:Why is assert is defined as (void)0?。 (不是重复的,因为它专注于另一种选择,但将来发现这个问题的人可能会感兴趣。) @JaMiT 我不相信链接问题中给出的答案。所以我决定在Visual C++ 中问同样的问题。我在那里得到了 Igor Tandetnik 的精彩回答。 * 耸耸肩 * Igor 确实给出了一个很好的例子。但是,您可能会注意到此页面上的某个位置(在宽浏览器中位于右侧,在窄浏览器中位于底部)现在有一个“链接”部分,其中包含指向 “为什么断言定义为 (void)0? ".我可以通过添加评论向该部分添加相关的 SO 问题。添加相关的非 SO 问题并不是那么简单。 ;) 【参考方案1】:这可以防止使用assert
作为表达式。因此,如果有人这样做(错误地):
a = assert(something);
编译器会在发布和调试版本中抛出错误。
【讨论】:
我花了一段时间才接受你说的话。但你的答案是正确的。顺便说一句,答案很好! @Belloc 不一定只有一个“正确”的答案;可能有多种原因。此外,这个答案有点不准确。(void)
演员表防止 assert()
成为 rvalue,但它仍然可以用作 expression。例如:condition ? assert(something) : assert(somethingElse)
或 assert(condition), puts("hello")
。
@jamesdlin 你会发现我接受 Julien 的回答而不是你的here 的原因。基本上,朱利安的回答似乎更好地解释了这个例子,因为在这种情况下没有警告。我还注意到朱利安的回答有一点不准确。但在我看来,这是一个很小的问题,不能做出有利于他的决定。【参考方案2】:
一些编译器可能希望 (void)
强制转换来抑制有关未使用值的表达式的警告。
【讨论】:
以上是关于为啥在发布版本中断言宏的定义不能只是`#define assert(expression) 0`?的主要内容,如果未能解决你的问题,请参考以下文章