tags:

views:

324

answers:

5
+2  Q: 

MIN and MAX in C

Where are MIN and MAX defined in C, if at all? What is the best way to implement these, as generically and type safe as possible (compiler extensions/builtins for mainstream compilers preferred).

+3  A: 

There's a std::min and std::max in C++, but AFAIK, there's no equivalent in the C standard library. You can define them yourself with macros like

#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))

But this causes problems if you write something like MAX(++a, ++b).

dan04
A: 

Here's some gcc doc about min/max: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Min-and-Max.html

RC
That's a C++-only extension. It says it is not available in GNU C.
dreamlax
I know I was linking for the part about MIN and MAX macro, i.e. "The GNU C typeof extension allows you to write safe macros that avoid this kind of problem (see Typeof)"
RC
You should have provided a link to [*there*](http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Typeof.html#Typeof) instead, especially considering it contains an actual example implementation of `max` using the `typeof` extension.
dreamlax
+2  A: 

I don't think that they are standardised macros. There are standardised functions for floating point already, fmax and fmin (and fmaxf for floats, and fmaxl for long doubles).

You can implement them as macros as long as you are aware of the issues of side-effects/double-evaluation.

#define MAX(a,b) ((a) > (b) ? a : b)
#define MIN(a,b) ((a) < (b) ? a : b)

In most cases, you can leave it to the compiler to determine what you're trying to do and optimise it as best it can. While this causes problems when used like MAX(i++, j++), I doubt there is ever much need in checking the maximum of incremented values in one go. Increment first, then check.

dreamlax
+4  A: 

Where are MIN and MAX defined in C, if at all?

They aren't.

What is the best way to implement these, as generically and type safe as possible (compiler extensions/builtins for mainstream compilers preferred).

As functions. I wouldn't use macros like #define MIN(X,Y) ((X) < (Y) ? : (X) : (Y)) , especially if you plan to deploy your code. Either write your own or use something like http://www.gnu.org/s/libc/manual/html_node/Misc-FP-Arithmetic.html#Misc-FP-Arithmetic or fix the macro using http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Typeof.html#Typeof (you get typesafety bonus too):

 #define max(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a > _b ? _a : _b; })

Everyone says "oh I know about double evaluation, it's no problem" and a few months down the road, you'll be debugging the silliest problems for hours on end.

Edit: note the use of __typeof__ instead of typeof:

If you are writing a header file that must work when included in ISO C programs, write __typeof__ instead of typeof.

David Titarenco
If you know `MAX` is a macro, and you *still* provide an expression with side-effects, then you've shot yourself in the foot. I seriously cannot think of a situation where one needs to provide an expression with side-effects to a macro *or* function that determines a maximum value.
dreamlax
You have a point :) But I'd rather be safe than sorry.
David Titarenco
You know, it'd be quite handy if gcc had a warning along the lines of: `warning: expression with side-effects multiply evaluated by macro` at the point of use...
caf
@caf: wouldn't that require that the preprocessor have a more complicated knowledge of C syntax?
dreamlax
@dreamlax: I was thinking that the preprocessor could leave annotations behind at the point of each macro expansion when a parameter was used more than once, which the compiler could then use.
caf
For the win, can you link to, or provide details for how to achieve this on Visual-C++?
Matt Joiner
Or any other C compiler that is not GCC?
Luther Blissett
After much trying to figure out, I don't think there's anyway to do this in VC++, but your best best is to try to mess with MSVC++ 2010 new `decltype` keyword -- but even so, Visual Studio can't do compound statements in macros (and `decltype` is C++ anyway), i.e. GCC's `({ ... })` syntax so I'm pretty sure it's not possible, anyway. I haven't looked at any other compilers regarding this issue, sorry Luther :S
David Titarenco
A: 

It's also provided in the GNU libc (Linux) and FreeBSD versions of sys/param.h, and has the definition provided by dreamlax.


On Debian:

$ uname -sr
Linux 2.6.11

$ cat /etc/debian_version
5.0.2

$ egrep 'MIN\(|MAX\(' /usr/include/sys/param.h
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

$ head -n 2 /usr/include/sys/param.h | grep GNU
This file is part of the GNU C Library.

On FreeBSD:

$ uname -sr
FreeBSD 5.5-STABLE

$ egrep 'MIN\(|MAX\(' /usr/include/sys/param.h
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

The source repositories are here:

Mikel
Where? Can you give a link?
Matt Joiner
I've added the definitions from the systems I have access to in my answer above (the comment field doesn't accept formatting as far as I can tell).Will try to find the links to the FreeBSD/Linux/glibc source repos.
Mikel
Links added above.
Mikel