【发布时间】:2020-12-25 11:50:11
【问题描述】:
在 Visual Studio 中,断言宏的定义如下:
#define assert(expression) (void)( \
(!!(expression)) || \
(_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
)
我在 || 之后得到了正确的部分仅当左表达式为 false 时才计算,并引发异常。
我有 3 个问题:
-
!!双重否定是将'表达式'类型转换为布尔值,对吗?如果他们被排除在外,会发生什么?当 ' 表达式与另一个表达式进行逻辑或运算时,它会被隐式转换为布尔值,对吗?在:
浮动() || /* 调用抛出的函数*/;
float() 还是转换成 bool 类型?
2.在||之后我们有运算符:
( /* call function that throws */ , 0 )
逗号是一个序列点,所以首先调用函数,然后这个表达式被评估为 0。如果函数调用没有终止程序,那么表达式就是:
!!(expression)) || 0
逗号后面的 0 有什么意义?如果 if 不存在,则表达式为:
!!(expression)) || / * call function that throws */
哪个是一样的,对吧?
- 最后是 (void),我想知道这是干什么用的。
【问题讨论】:
-
如果我有一个类型(愚蠢地?让我们怀疑并假设有充分的理由)覆盖
operator||怎么办?嗯,可能((bool)(expression) || ...会更安全。他们也可能已经覆盖了operator!。 -
需要逗号运算符,因为
_wassert返回void。而_wassert没有throw,它要么以退出代码 3 中止,进入调试器,要么忽略问题并继续。可以使用_set_error_mode更改其行为。该宏还使用带有if语句的宏来避免悬空 else 问题,并且有点聪明,因为它将其保留为 表达式 而不是 语句。 -
最顶层的
(void)是为未使用的表达式结果压制编译器警告,并防止意外使用表达式结果。而且宏可能和编译为C或C++或C++/CLI时使用的宏是一样的,所以必须满足这些语言的交集。 -
@Eljay,很酷,现在让它成为答案 :)