2015-02-11 45 views
3

我寫的程序如下:不能正常工作

#include<cstdio> 
#define max(a,b) a>b?a:b 
using namespace std; 

int main() 
{ 
    int sum=0,i,k; 
    for(i=0;i<5;i++) 
    { 
     sum=sum+max(i,3); 
    } 
    printf("%d\n",sum); 
    return 0; 
} 

我得到的輸出:4

但是,當我在一個變量k存儲max(i,3)和然後添加到sum,我得到了正確的輸出:

#include<cstdio> 
#define max(a,b) a>b?a:b 
using namespace std; 

int main() 
{ 
    int sum=0,i,k; 
    for(i=0;i<5;i++) 
    { 
    k=max(i,3); 
    sum=sum+k; 
    } 
    printf("%d\n",sum); 
    return 0; 
} 

輸出:16

有人可以請解釋爲什麼會發生?

+1

總是使用parens來定義帶參數的宏(a> b)?a:b) – BsD 2015-02-11 14:47:13

+0

因爲它是一個宏。 – 2015-02-11 14:47:17

+3

@BsD,這是宏應儘可能避免的確切原因。您的更正仍然缺少括號:'((a)>(b)?(a):(b))' – chris 2015-02-11 14:49:49

回答

5

散列定義宏是一個字符串擴展,而不是「語言」的東西。

sum=sum+max(i,3); 

擴展爲:

sum=sum+i>3?i:3; 

如果你正在編寫與沒有()圓它,你應該得到錯誤的答案。試試這個:

#define max(a,b) (a>b?a:b) 

但仍有許多情況下它會失敗。正如其他人指出一個更好的宏:

#define max(a,b) ((a)>(b)?(a):(b)) 

但它仍然失敗在太多的情況下,如副作用越來越兩次評估參數。你是多少好得多避免宏在可能情況下,做這樣的事情:

template <typename T> T max(T a, T b) { return a>b?a:b; } 

或者,事實上,使用std ::最大且已經爲你寫的std ::分鐘!

+1

你的宏可以很容易被有效的參數打破。切換註釋行進行比較:http://coliru.stacked-crooked.com/a/69619687946a13f3 – chris 2015-02-11 14:53:40

+1

是的,或者只是在其中一個參數中使用++運算符,這是破解宏的經典方法。我確實說過有些情況會失敗。編輯並添加了「many」:p – 2015-02-11 15:30:24

+0

是的,但++兩次使用兩次參數不能輕易避免,而這個可以通過額外的括號。 – chris 2015-02-11 15:33:28

1

的prepocessor(與-E標誌觀看)的輸出將是:

sum = sum+i>3?i:3; 

這是一樣的

sum = (sum+i)>3?i:3; 

這是不是你的意思,因爲+高於優先於>。您應該使用:

#define max(a,b) (a>b?a:b) 

改爲。

+1

你的宏可以很容易被有效的參數打破。切換註釋行以進行比較:http://coliru.stacked-crooked.com/a/69619687946a13f3 – chris 2015-02-11 14:54:52

2

我認爲你有運算符優先級問題,你必須記住,定義會導致你的源代碼中的文本替換。你應該改變你的定義來

#define max(a,b) ((a) > (b) ? (a) : (b)) 
1

在該行sum=sum+max(i,3);更換您的宏給出瞭如下形式:

sum=sum+i>3?i:3 ; 

這是問,如果sum + i大於3比分配總和的價值相應。因此,您有4個,因爲每次在循環內發生新的分配。使用Andrew建議的模板方法。

(循環對條件求每次(sum + i) > 3 ? i : 3沒有累加這裏。)

3

這條線:

sum=sum+max(i,3); 

擴展爲:

sum = sum + i > 3 ? i : 3; 

其中,集時與parens更清晰的是:

sum = (sum + i) > 3 ? i : 3; 
因此,對通過循環5遍遍

,表達式爲:

sum = (0 + 0) > 3 ? 0 : 3; // Result, sum = 3 
sum = (3 + 1) > 3 ? 1 : 3; // Result: sum = 3 
sum = (3 + 2) > 3 ? 2 : 3; // Result: sum = 3 
sum = (3 + 3) > 3 ? 3 : 3; // Result: sum = 3 
sum = (3 + 4) > 3 ? 4 : 3; // Result: sum = 4 

這正是你的答案來源。

解決這個傳統的方法是改變#define到:

#define max(a,b) (((a)>(b))?(a):(b)) 

但是,即使這有一定的缺陷。