2012-10-20 77 views
9

我試圖用下面的公式做一個宏:(a^2/(a+b))*b,我想確保不會有零除。是否有可能在#define中使用if語句?

#define SUM_A(x, y) if(x == 0 || y == 0) { 0 } else { (((x * x)/((x) + (y))) * (y))} 

,然後我叫宏內部主:

float a = 40, b = 10, result; 
result = SUM_A(a, b); 
printf("%f", result); 

我試着使用括號周圍IF函數,但我一直在if語句之前得到語法錯誤。我也嘗試過使用return,但是我在某處讀過你不應該在define中使用它的地方。

回答

14

因爲#define由預處理器解釋不能使用if語句,以及輸出將

result=if(x == 0 || y == 0) { 0 } else { (((x * x)/((x) + (y))) * (y))} 

這是錯誤的語法。

但是另一種方法是使用三元運算符。改變你的定義來

#define SUM_A(x, y) ((x) == 0 || (y) == 0 ? 0 : ((((x) * (x))/((x) + (y))) * (y))) 

記住,總是把你的括號中的定義,更換時要避免語法錯誤。

+1

說到括號,不應該是'(x)*(x)','(x)== 0'和'(y)== 0'嗎?確實是 – SirGuy

+0

。感謝您指出了這一點。 – tomahh

+0

非常感謝,我從來沒有聽說過這個運營商。 – Frey1337

5

if引入了一個語句,而不是一個表達式。使用「三元」(條件)運算符:

#define SUM_A(x, y) (((x) == 0 || (y) == 0)? 0: ((((x) * (x))/((x) + (y))) * (y))) 

可替換地,使此一inline功能:

inline float sum_a(float x, float y) 
{ 
    if (x == 0 || y == 0) 
     return 0; 
    else 
     return ((x * x)/(x + y)) * y; 
} 

這避免了x和/或y多個評價的問題,並且是更可讀,但它確實修復了xy的類型。您也可以刪除inline並讓編譯器確定是否值得內聯此函數(inline不保證它將執行內聯)。

+0

該函數的麻煩是它迫使你使用'float'作爲你的數據類型。也許沒關係,但也許沒有。 – SirGuy

+0

@GuyGreer:好點,補充說,答案。 –

1

問題是if語句不是表達式,並且不返回值。此外,在這種情況下使用宏沒有任何理由。事實上,它可能會導致非常嚴重的性能問題(取決於您作爲宏參數傳遞的內容)。你應該使用一個函數。

0

有與您的宏多種問題:

  • 它擴展爲一個語句,所以你不能把它作爲一種表達

  • 參數都沒有在擴展正確括號:調用此除了變量名或常量之外的任何宏都會產生問題。

  • 參數被多次評估:如果您使用具有副作用的參數調用宏,如SUM_A(a(), b())SUM_A(*p++, 2),副作用將多次出現。

爲了避免這些問題,使用功能,可能定義爲static inline,幫助編譯器優化多(這是可選的,現代的編譯器自動執行此操作):

static inline int SUM_A(float x, float y) { 
    if (x == 0 || y == 0) 
     return 0; 
    else 
     return x * x/(x + y) * y; 
} 

注:

  • 該函數使用浮點運算,宏不一定會根據它的實際類型來進行計算。
  • 該測試不會阻止被零除:SUM_A(-1,1)仍然執行一個。
  • 除零不一定是個問題:使用浮點參數時,它會產生Infinity或NaN,而不是運行時錯誤。
1

從技術上講,可以在#define中使用if語句(但不會以您期望的方式)。由於#define只是文本替換,所以您必須非常小心如何擴展它。我發現,這個工程......

#define SUM_A(x, y)        \ 
({            \ 
    double answer;        \ 
    if (x == 0 || y == 0)      \ 
     answer = 0;        \ 
    else          \ 
     answer = ((double)(x*x)/(x+y)) * y; \ 
    (answer);         \ 
}) 
// Typecasting to double necessary, since int/int rounds down to int in C 

這應該給你你正在尋找的結果,而且也沒有理由不能推廣到包括多個else if S以及(雖然其他答案有指出,它可能更容易使用三元運算符)。

1

是的,你可以在宏中有一條if語句。您需要正確格式化。這裏是一個例子:

#define MY_FUNCTION(x) if(x) { PRINT("TRUE"); } else { PRINT("FALSE"); } 
相關問題