2015-07-06 78 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