2012-02-26 69 views
0

讓我解釋一下我的示例代碼混淆C宏擴展如何工作?

這是我們宏觀

#define rsAssert(v) if(!(v)) printf("rsAssert failed: %s, in %s at %i" #v, __FILE__, __LINE__); 

案例1:

int main(void) 
{ 
    rsAssert(0); 
    return 0; 
} 

這種情況下編譯成功地

情況下2

int main(void) 
{ 
    rsAssert(0) // note here ; is not present 
    return 0; 
} 

這也編譯succsfully 問題1:

這意味着無論你寫rsAssert(0)rsAssert(0);它們之間沒有什麼區別?


然後

情況下3

int main() 
{ 
    if(1) 
    rsAssert(0); 
    else 
    printf("mr.32"); 
    return 0; 
} 

這裏rsassert(0);不會編譯[見http://ideone.com/7dFv1]但沒有;rsasser(0)正常工作[見http://ideone.com/8fehl] ..

我沒有得到宏前的事情pansion在這裏...

回答

4

它不在的情況下3個工作的原因是因爲這是實際上是越來越編譯:

int main() 
{ 
if(1) 
    if(!(v)) printf("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__);; 
else 
    printf("mr.32"); 
return 0; 
} 

注意多餘的分號在距離第一個printf結束宏。

通常情況下,使用if語句時,後跟單個語句或帶{}的塊。

的,因爲額外不過,你有這樣的:

if (...) 
    printf(...); ; 
else 
    printf(...); 
return 0; 

那多餘的分號是一個空語句,但仍然是一個聲明不過。

您應該刪除;來自宏觀。那麼事情會更有意義。

+0

哦,謝謝了它的整個事情..在情況1它有一個;這是空的語句,並在情況2是完美的,但情況2使用rsassert(0);額外的案件;這造成問題... – 2012-02-26 06:17:07

+1

是的。簡單地說,當在C中查看宏替換時,它幾乎可以直接複製到文件中。他們並沒有真正的自己的語義。 – 2012-02-26 15:50:56

2

它根本不工作在情況3,我期望。做手工的擴展功能(縮進它是有道理的):

int main() 
{ 
    if (1) 
    if(!(0)) 
     printf("rsAssert failed: %s, in %s at %i", "0", __FILE__, __LINE__); 
    else 
     printf("mr.32"); 
    return 0; 
} 

正如你所看到的,else與錯誤if語句結束了。如果你想要一個包含if語句的宏來工作,你需要使它看起來像一個簡單的語句。在do... while(0)結束語是地道:

#define rsAssert(v)               \ 
    do {                 \ 
     if(!(v))                \ 
     printf("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__); \ 
    } while (0) 
+1

+1,用於提倡'do-while(0)'。 – jamesdlin 2012-02-26 10:41:54

1
if(1) 
    rsAssert(0); // Original semicolon 
else 
    .... 

擴展到

if(1) 
    if(!(v)) printf("rsAssert failed: %s, in %s at %i", 
     #v, __FILE__, __LINE__);; // Notice the extra semicolon. The extra from the 
           // macro expansion. 
else 
    .... 

這多餘的分號導致一個新的空語句。由於沒有{},對於if語句,else沒有立即遵循,這是編譯器在抱怨什麼。所以,做 -

if(1) 
{ 
    rsAssert(0); 
} 
else 
    .... 
4

這是我始終強制我的程序員在所有if語句中使用body的最大原因。

int main() 
{ 
    if (1) 
    if(!(0)) 
     printf("rsAssert failed: %s, in %s at %i", "0", __FILE__, __LINE__); 
    else 
     printf("mr.32"); 
    return 0; 
} 

良好的編碼標準

int main() 
{ 
    if (1){ 
    if(!(0)){ 
     printf("rsAssert failed: %s, in %s at %i", "0", __FILE__, __LINE__); 
     } 
    } 
    else { 
     printf("mr.32"); 
    } 
    return 0; 
} 

修復了變化列出吹塑的低成本防止。

#define rsAssert(v) (printf((!v)?"rsAssert failed: %s, in %s at %i":"", #v, __FILE__, __LINE__)) 

這將工作,但將始終做一個printf。

#define rsAssert(v) ((!v)?printf("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__):0) 

這將只打印出來,如果你絆倒的斷言,但凌亂尋找

還要考慮以下!

if(rand()%2) 
    FooLog("Hello World"); 
ImportantFunction(); 

#if DEBUG 
#define FooLog printf 
#else 
#define FooLog // 
#endif 

在發佈中,重要函數在50%的時間內100%的時間內工作。

+0

哈哈很好趕上... !!! – 2012-02-26 06:23:47

+0

爲你增加了另一種情況。 – Nico 2012-02-26 06:33:53