2012-06-06 62 views
0

可以說我定義一個宏:定義一個宏用C

#define MAX(x,y) ((x)>(y)?(x):(y)) 

如果我叫MAX(I++,J++)會發生什麼?

我不明白爲什麼答案不會如預期。

+10

你得到了什麼答案?你期望什麼答案? – Krishnabhadra

回答

6

宏僅供預處理器使用。這就是將C編譯器被編譯:

(((I++)>(J++))? ((I++):(J++))) 

正如你所看到的,如果我是大大於j,然後我會得到增加兩次和J一次,否則它反之亦然。


你的宏是不正確的。括號中的外層是錯在這裏,這將導致編譯錯誤:

((I++):(J++)) 
+3

值得一提的是:它是定義的行爲,因爲在評估左操作數之後存在序列點(布爾型編碼)。這在宏中不是微不足道的,例如:'MAX(I ++,I ++)'會導致未定義的行爲,因爲'I'在同一個表達式中增加了兩次。 – amit

2

MAX(I++,J++)將擴大至(((I++)>(J++))? ((I++):(J++)))。請注意,有兩次出現I++J++,所以在比較之後它們都會增加,然後取得的結果將再次遞增。

你可以使用內聯函數:

inline int MAX(int x, int y) 
{ 
    return x > y ? x : y; 
} 

但我想宏觀對任何類型的工作的優勢。

+0

,除非I和J是64位整數...... – Shahbaz

+0

正如我所說的,我認爲這個宏具有爲任何類型工作的優勢(而你需要爲每個類型使用不同的函數)。 –

1

int res = MAX(x,y);宏將花費到

(((x) > (y)) ? (x):(y)); 
現在

如果x = a++y = b++中條件不錯,將轉化爲

(((a++) > (b++)) ? (res = a++):(res = b++)); 

因此,對於路徑,無論哪個變量是意志總共兩次,但存儲在res中的結果值只會有一個增量(因爲您正在使用後增量)。

在函數/宏調用中使用post-inc可能會非常棘手,因爲它們會引入細微的邏輯故障。

更喜歡按照原樣將變量傳遞給函數/宏,並對其進行獨立的更改,這將爲您節省這類問題的時間。