2015-07-06 118 views
1

爲什麼下面的代碼不工作?它打印INT_MAX。但是如果我取消註釋循環內部的兩行,那麼它工作正常(打印2)。我不能把這兩個宏組合起來?不知道是否需要進一步的細節...很自我解釋。C++宏(min max)無法正常工作

謝謝。周圍的術語

#include <iostream> 
#include <limits.h> 

using namespace std; 

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

int main(int argc, char **argv) 
{ 
    int N = 100; 
    int *drop = new int[N+1]; 
    drop[0] = 0; drop[1] = 1; drop[2] = 1; 
    for(int i=3; i<=N; i++) 
    { 
     drop[i] = INT_MAX; 
     for(int start=1; start<=i; start++) 
     { 
      drop[i] = min(drop[i], max(start, drop[i-start]+1)); 
      //int x = max(start, drop[i-start]+1); 
      //drop[i] = min(drop[i], x); 
     } 
    } 
    cout<<drop[3]<<endl; 
    return 0; 
} 
+1

使用庫函數,因此您不允許使用'min(35,「frog」)'',因爲您使用了宏並且宏沒有類型檢查,所以這是允許的。 –

回答

7

括號括起來,在您的宏:

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

正因爲如此,這樣的:

drop[i] = min(drop[i], max(start, drop[i-start]+1)); 

是擴大到這個(不帶括號):

drop[i] <start> drop[i-start]+1 ? start: drop[i-start]+1 ? drop[i] : start > drop[i-start]+1 ? start: drop[i-start]+1; 

可能無法按照您的順序評估d。使用括號會強制執行正確的操作順序。

如註釋中所述,如果宏參數多次計算,則不應使用具有副作用的表達式的宏。

+1

這仍然是*非常*錯誤:諸如'min(x ++,y)'等表達式會導致'x'無意中的雙重增量。在2分鐘內看到我的答案。 – Michael

+0

@Michael你不應該對帶有副作用的表達式使用宏。這可以說是使用宏而不是宏本身的問題。在OP的例子中,傳遞給宏的表達式沒有副作用。 – samgak

+2

@邁克爾:只是因爲宏可能是危險的並不意味着他們錯了。你只是應該知道你在做什麼。 – AnT

7

C++已經在<algorithm>中定義了std::minstd::max。您可以將您的代碼更改爲純C++版本

#include <iostream> 
#include <algorithm> 
#include <limits> 
using namespace std; 

int main(int argc, char ** argv) { 
    int N = 100; 
    int * drop = new int[N + 1]; 
    drop[0] = 0; 
    drop[1] = drop[2] = 1; 
    for (int i = 3; i <= N; ++i) { 
     drop[i] = numeric_limits<int>::max(); // <limits> 
     for(int start = 1; start <= i; ++start) 
      drop[i] = min(drop[i], max(start, drop[i - start] + 1)); // <algorithm> 
    } 
    cout << drop[3] << endl; 
    return 0; 
} 
+0

標記samgak的回答爲答案,因爲它解決了我的困惑,但我想我應該使用內置的東西。但究竟是bits/stdC++。h ...你說這是在,但包含了其他的東西。我根本不使用C++。 – shek

+1

@shek bits/stdC++是一個包含所有C++頭文件的頭文件。但是,別擔心我會編輯它。 – Shreevardhan

+0

好的。謝謝。對bit/stdC++只是好奇。h – shek

6

不是一個答案,這是一個懇求所有開發人員在那裏:請不要使用這樣的宏。 C++爲這些目的提供了模板函數。請記住,宏只是替代參數,而不是預先評估它們。即使你像samgak解釋的那樣添加圓括號,這隻能解決一半的問題。考慮這樣的代碼:

int x = 5; 
int y = max(++x, 0); 

主叫方期望之後x=6y=6;然而,宏將得到消耗到

int y = (++x > 0)? ++x : 0; 

造成x=7y=7

+1

C++語言也允許*內聯*函數。 –

+1

@ThomasMatthews:是的,一個合適的解決方案就像'template inline T max(T x,T y){return x> y? x:y; }'更好的解決方案是使用'std :: max'。除了宏之外的任何東西。 – Michael

+1

函數不提供懶惰的評估語義。宏可以,這就是爲什麼宏不能被函數替換的原因。至少不是那麼簡單。 – AnT