This is one of my favourite interview question: What is wrong with this macro ?
#define MIN(a, b) ((a) < (b)) ? (a) : (b)))
I mean, it's in the GNU libc, so it should be pretty good:
grep MIN /usr/include/sys/param.h
#define MIN(a,b) ((a)<(b))?(a):(b))
$
Let me show you
#include <stdio.h>
#define min(a, b) ((a) < (b)) ? (a) : (b)
int main() {
int a = 1, b = 2;
printf ("%d\n", min (a, b));
printf ("a=%d, b=%d\n\n", a, b);
printf ("%d\n", min (a++, b++));
printf ("a=%d, b=%d\n\n", a, b);
}
$ gcc test.c && ./a.out
1
a=1, b=2
2
a=3, b=3
$
It's a classic trick: Double evaluation.
This is why cool kids are using this macro:
#define MIN(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
or even this one
#define MIN(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
Unfortunately, it's using some cancer GNU extension;
there is no way in ANSI C to get the type of a variable.
Of course, you could hardcode them (Or pass them as arguments, but this would be annoying (and you'll likely end using the GNU-specific statement as expressions extension, or worse, the blocks one)):
#define MIN(a,b) \
({ int _a = (a); \
int _b = (b); \
_a < _b ? _a : _b; })
But since you're losing macro's genericity, you might as well use an inline function like this one
inline int min(int a, int b) {
if (a > b)
return b;
return a;
}
Long story short: Don't use macro for MIN
and MAX
in C,
because you'll use them one day with a side-effect argument,
and then, Smokey, my friend, you will be entering a world of pain.
edit: It seems that this blogpost may make its way into cppcheck ;)