2014-01-11 39 views
1

我讀*(乘法)比/(除法)有更高的優先權。因此,如果存在與*/兩者的等式,則必須首先發生*乘法和除法:奇怪的輸出在c

但我見過一個程序,輸出一些奇怪的

#include<stdio.h> 
#define SQUARE(x) x*x 

int main() 
{ 
    float s=10, u=30, t=2, a; 
    a = 2*(s-u*t)/SQUARE(t); 
    printf("Result = %f", a); 
    return 0; 
} 

運行此,我認爲輸出是-25,但實際上卻是-100。

當我看到您的解釋是

Step 2: a = 2*(s-u*t)/SQUARE(t); becomes, 

// Here SQUARE(t) is replaced by macro to t*t 
=> a = 2 * (10 - 30 * 2)/t * t; 

=> a = 2 * (10 - 30 * 2)/2 * 2; 

=> a = 2 * (10 - 60)/2 * 2; 

=> a = 2 * (-50)/2 * 2 ; 

/*till here it's OK*/ 
/*why it divided -50 by 2 before multiplying 2*2 and -50*2 */ 
=> a = 2 * (-25) * 2 ; 

=> a = (-50) * 2 ; 

=> a = -100; 

任何一個可以解釋一下嗎?

+0

另一個參考:http://msdn.microsoft.com/en-us/library/126fe14k.aspx – Inisheer

+0

這有很多重複,例如,g [宏觀擴展的奇怪行爲](http://stackoverflow.com/questions/15337185/strange-behavior-of-macro-expansion) –

回答

6

括號偏執狂!你的宏應該是:

#define SQUARE(X) ((x)*(x)) 

否則優先規則和宏擴展會做奇怪的事情。您的宏:

100/SQUARE(2) 

將擴大到:

100/2*2 

和被讀爲:

(100/2) * 2 

是100,而不是25

其他異常,不你的代碼是如果你試圖平方的表達式:

SQUARE(2+2) 

將擴大到

2+2*2+2 

這是8,而不是預期的16

結論:在宏中寫了很多括號。到處。

+0

並非無處不在,只能圍繞宏觀參數(以及它們自然應該在哪裏)。 ;-) –

+0

@tristopia:是的,圍繞整個表達。我誇大其詞。 – rodrigo

+0

我現在非常感謝你 – Salahuddin

2

它不會做你認爲它的作用:步驟標誌着/*till here it's OK*/後,該操作在他們的正常秩序進行了乘法運算符,即從左到右:

=> a = 2 * (-50)/2 * 2 ; 
/*till here it's OK*/ 
=> a = -100/2 * 2 ; // Division 
=> a = -50 * 2 ;  // Multiplication 
=> a = -100 ;   // Done 

你的代碼是一個很好的例子爲什麼需要非常小心地使用宏:括號宏的參數可以解決這個問題,但是有些問題根本無法解決。例如,您的宏將保持不適合表達的副作用:

#define SQUARE(X) ((x)*(x)) 
// Still not good: 

int a = 2; 
// Undefined behavior, because ((a++)*(a++)) uses expressions with side effects without a sequence point 
int b = SQUARE(a++); 

出於這個原因,你會過得更好做SQUARE功能。