C++ assert宏的解释

C++ assert宏的解释,c++,C++,我无法评论答案本身,所以:关于 这里debugbreak()返回void,但我们仍然希望0作为右值 (debugbreak(),0)如何返回0?我知道debugbreak()的返回值被丢弃,返回0,但是debugbreak会生成一个异常,那么以后如何计算呢?我想我的问题可以推广到任何类似的二进制运算符,其中第一个被计算的部分退出程序。如果启动assert,则不会计算任何内容,但两个表达式都必须具有正确的返回类型,否则此宏将中断编译。这是一种类型系统攻击 #define MY_ASSERT(exp

我无法评论答案本身,所以:关于

这里debugbreak()返回void,但我们仍然希望0作为右值


(debugbreak(),0)如何返回0?我知道debugbreak()的返回值被丢弃,返回0,但是debugbreak会生成一个异常,那么以后如何计算呢?我想我的问题可以推广到任何类似的二进制运算符,其中第一个被计算的部分退出程序。

如果启动assert,则不会计算任何内容,但两个表达式都必须具有正确的返回类型,否则此宏将中断编译。

这是一种类型系统攻击

#define MY_ASSERT(expr) ((expr) || (debugbreak(), 0))
//   note the or operator here  ^
|
运算符接受两个
bool
类型的(或可转换的)表达式
debugbreak()
已键入
void
。要使其成为布尔值,请使用以下规则:

(FOO, BAR)
//    ^  determines the type of the entire comma expression

这与
{FOO;BAR}
相同,只是块(大括号中)没有类型。

基本思想非常简单。他试图获得与他所写的几乎相同的效果:
if(!expr)debugbreak()。但是,对于宏,他希望将其作为单个表达式。为此,他使用了
| |
,它计算它的左参数,然后当且仅当该参数为false时,才计算右参数,然后生成两个操作数的逻辑OR的整体结果

在这种情况下,他并不真正关心逻辑或结果;他只想计算左边,如果是假的话,计算右边。然而,编译器确实很在意——特别是,它要求
|
的两个操作数都具有某种可以转换为bool的类型(或者,在C中为0或1)


为了让编译器知道这一点,他使用逗号运算符,它先计算左操作数,然后计算右操作数,并生成右操作数的值作为结果。这让他可以得到
debugbreak()
的计算结果,而
0
通过给它一个int作为结果值来让编译器满意,它可以使用int或
expr
生成的任何值来生成整个表达式的结果(当然,这是不相关的,几乎肯定会被忽略).

我认为你所缺少的是(A | | B)遵循短路规则这一事实

如果A为true,则无需对B求值。因为不需要对B求值,所以永远不会调用DebugBreak()

如果A为false,那么我们必须计算B以确定(A | | B)的输出。没有短路。(DebugBreak(),0)或更合适的(DebugBreak(),false)


+1换句话说,您不能使用
无效的逻辑或,但可以使用
int
。请单击前面问题旁边的复选标记,接受前面问题的部分答案。如果你这样做,下次这里的人会更愿意帮助你。对不起,我的浏览器主题通常会使大多数元素不可见,所以除非我正在寻找它们,否则我往往不知道它们。谢谢你告诉我,我现在就去找“接受”按钮。顺便说一句,没有人对我收到的错误发表评论,所以如果有人在意,请看我在问题中为强调这一点而添加的最后一行。为什么不把你的主题改成真正有效的东西呢?因为有了主题,眼睛就不那么紧张了。并非必须查看所有内容,但在必要时,我将其关闭,因为修复某些内容的可见性并不明显。警告,迂腐:“它要求
|
的两个操作数都具有某种类型,可以转换为”
bool
;不是0或1。(当然,<代码> Boo.<代码>可以转换成另一个整数类型,这将导致0或1。)@ GMY:YUP——不知何故,当我在写时,我认为标签表示C而不是C++。更正。
(FOO, BAR)
//    ^  determines the type of the entire comma expression