2011-02-28 105 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