Title: MIN and MAX macro considered harmful
Date: 2015-02-17 20:00

This is one of my favourite interview question:
What is wrong with this macro ?

```c
#define MIN(a, b) ((a) < (b)) ? (a) : (b)))
```

I mean, it's in the GNU libc, so it should be pretty good:

```c
grep MIN /usr/include/sys/param.h 
#define MIN(a,b) ((a)<(b))?(a):(b))
$
```

Let me show you

```c
#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);
}
```

```bash
$ 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:

```c
 #define MIN(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a < _b ? _a : _b; })
```
or even [this one]( http://lxr.free-electrons.com/source/arch/powerpc/boot/types.h#L15 )

```c
#define MIN(x,y) ({ \
	typeof(x) _x = (x);     \
	typeof(y) _y = (y);     \
	(void) (&_x == &_y);    \
	_x < _y ? _x : _y; })
```

Unfortunately, it's using some <s>cancer</s> 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]( https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html) extension,
or worse, the [blocks]( https://en.wikipedia.org/wiki/Blocks_%28C_language_extension%29 ) one)):

```c
#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

```c
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]( https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=778659 ) ;)
