断言宏的解释

时间:2011-02-28 06:37:33

标签: c++

我无法评论答案本身,所以:关于Using comma to prevent the need for brace pair

 #define MY_ASSERT(expr) ((expr) || (debugbreak(), 0))
  

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

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

4 个答案:

答案 0 :(得分:4)

这是一种类型系统黑客。

#define MY_ASSERT(expr) ((expr) || (debugbreak(), 0))
//   note the or operator here  ^

||运算符采用两个bool - 类型(或可转换)表达式。 debugbreak()void - 已键入。要使其bool,请使用以下规则:

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

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

答案 1 :(得分:1)

如果断言触发,则不会评估任何内容,但两个表达式必须具有正确的返回类型,否则此宏将破坏编译。

答案 2 :(得分:1)

基本想法非常简单。他试图得到一个效果,就像他写的那样:if (!expr) debugbreak();。然而,对于宏,他希望将其作为单个表达式。为此,他使用||来评估它的左参数,然后当且仅当它为假时,计算正确的参数 - 然后产生一个整体结果,即两个操作数的逻辑或。

在这种情况下,他并不真正关心关于作为结果产生的逻辑OR;他只想要评价左边,然后如果是假的评价右边。编译器,但 非常关心 - 特别是,它要求||的两个操作数都有一些可以转换为bool(或者,在C,0或1中)的类型。 / p>

为了给编译器,他使用逗号运算符来计算其左操作数,然后使用右操作数并生成右操作数的值作为结果。这让他得到了debugbreak()的评估,而0通过给它一个int作为结果值来保持编译器的快乐,然后它可以与expr产生的任何值进行OR运算。产生整体表达的结果(当然,这是无关紧要的,几乎肯定会被忽略)。

答案 3 :(得分:0)

我认为你所有人都缺少的是(A || B)遵循短路规则的事实。

如果A为真,则无需评估B.因为不需要评估B,所以DebugBreak()永远不会被调用。

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

http://www.student.cs.uwaterloo.ca/~cs132/Weekly/W02/SCBooleans.html

http://msdn.microsoft.com/en-us/library/zs06xbxh(VS.80).aspx