Reputation: 215
Why doesn't the following code work? It prints INT_MAX. But if I uncomment the two lines in the inner for loop, then it works fine (prints 2). I can't combine the two macros like that? Not sure if further detail is needed...pretty self explanatory.
Thanks.
#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;
}
Upvotes: 3
Views: 14831
Reputation: 12641
C++ already has std::min
and std::max
defined in <algorithm>
. You can change your code to a pure C++ version
#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;
}
Upvotes: 9
Reputation: 5897
Rather than an answer, it's a plead to all developers out there: please don't use macros like that. C++ offers template functions for these purposes. Remember that macros just substitute parameters rather than pre-evaluating them. Even if you add parentheses as samgak explained, this only fixes a half of the problem. Consider code like this:
int x = 5;
int y = max(++x, 0);
The caller would expect x=6
and y=6
after that; however the macro will get expended into
int y = (++x > 0)? ++x : 0;
causing x=7
and y=7
.
Upvotes: 8
Reputation: 24417
Put brackets around the terms in your macros:
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
As it is, this:
drop[i] = min(drop[i], max(start, drop[i-start]+1));
is expanding to this (without brackets):
drop[i] < start > drop[i-start]+1 ? start: drop[i-start]+1 ? drop[i] : start > drop[i-start]+1 ? start: drop[i-start]+1;
which may not evaluate in the order you intend. Using brackets enforces the correct order of operations.
As noted in the comments, you shouldn't use macros with expressions that have side effects if the macro arguments are evaluated more than once.
Upvotes: 12