2011-02-28 77 views
8

我无法对答案本身发表意见,所以:约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会生成一个异常,那么以后如何评估任何东西?我想我的问题可以概括为任何类似的二元运算符,其中第一部分被评估退出程序。

+0

通过单击旁边的复选标记,请接受一些答案您以前的问题。如果你这样做,这里的人会更乐意帮助你下一次。 – 2011-02-28 06:41:04

+0

对不起,我的浏览器主题通常会让大多数元素不可见,所以除非我正在寻找它们,否则我倾向于不知道它们。谢谢你告诉我,我现在去找接受按钮。顺便说一下,没有人对我收到的错误提出了这样的问题,所以如果有人在意,请参阅我在问题中添加的最后一行以强调这一点http://stackoverflow.com/questions/5138609/why-does-main-需要拉条。 – user490735 2011-02-28 06:43:18

+2

你为什么不改变你的主题,以实际的作品? – GManNickG 2011-02-28 07:19:21

回答

1

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

+2

+1换句话说,你不能逻辑 - 或用'void',但你可以用'int'。 – GManNickG 2011-02-28 06:41:01

4

这是一个类型系统破解。

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

||操作者需要两个bool -typed(或可转换)的表达式。 debugbreak()void-type。为了使它bool,使用以下规则:

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

这是相同{FOO; BAR}不同之处在于一个块(在括号中)没有类型。

1

基本想法很简单。他试图得到与他写作一样的效果:if (!expr) debugbreak();。然而,对于一个宏而言,他希望这是一个单一的表达。为此,他使用||来评估它的左边参数,然后当且仅当它是false时才评估正确的参数 - 然后产生一个总体结果,即两个操作数的逻辑或。

在这种情况下,他并不真的关心关于那个作为结果产生的逻辑或;他只是想评估左边,然后如果它是错误的评估正确。但编译器的确注意了,特别是它要求||的两个操作数都有一些可以转换为bool的类型(或者在C,0或1中)。

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

+0

警告,pedantry:“它要求'||'的两个操作数都有一些可以转换为”bool“的类型;不是0或1.(当然,一个'bool'可以转换为另一个整数类型,这将导致0或1)。 – GManNickG 2011-02-28 07:04:25

+0

@GMan:是的 - 不知何故,当我写作时,我认为标签说C而不是C++。纠正。 – 2011-02-28 07:08:37

+0

啊,没问题。 :) – GManNickG 2011-02-28 07:11:53

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