30

I'm using two computers, each with a different version of visual studio. On the visual studio 2008 computer my code compiles. On the visual 2010 computer my code doesn't compile because I'm using the macro max(a,b) which as far as I know is defined in stdlib.h. I cannot just define max(a,b) because it'll be a redefinition on the visual 2008 computer. But if I don't define max(a,b) my code doesn't compile on the visual 2010 computer.

Any solution?

snakile
  • 52,936
  • 62
  • 169
  • 241
  • Aside from the portability problems discussed in the accepted answer, I'm curious why you have problems with moving code using the `max()` macro from VS2008 to VS2010. `max()` is defined in VS2010's `stdlib.h` in the same way that it is in VS2008 (there are options which will turn off the definition, but they're the same in both compilers). In other words, there's something more than just the move from VS2008 to VS2010 (and that `max()` being defined in `stdlib.h` is non-standards conforming) that caused this problem for you. – Michael Burr Nov 22 '10 at 20:06
  • On my Visual C the stdlib.h defines `__min` and `__max`. – Calmarius May 26 '14 at 15:39
  • http://stackoverflow.com/questions/3437404/min-and-max-in-c – Ciro Santilli OurBigBook.com Nov 02 '16 at 07:00
  • In visual studio 2015, min and max are still defined in stdlib.h... – Ruben Nov 28 '16 at 12:06
  • @Ruben, I had the same problem, running Visual Studio 2022 of `min()` and `max()` being defined in `stdlib.h` which was annoying because I had defined my own. Solved it by defining `#define __STDC__ 1` before including `stdlib.h`. – carsonalh Jul 14 '23 at 06:53

5 Answers5

42

Any C library which defines a macro named max in its standard headers is broken beyond imagination. Fortunately, an easy workaround if you need to support such platforms is to #undef max (and any other problematic macros it defines) after including the system headers and before any of your own headers/code.

Note that everyone else is saying to wrap your definition in #ifndef max ... #endif. This is not a good idea. Defining max in a system header is an indication that the implementor was incompetent, and it's possible that certain versions of the environment have incorrect macros (for example, ones which do not properly protect arguments with parentheses, but I've even seen a max macro that was incorrectly performing min instead of max at least once in my life!). Just use #undef and be safe.

As for why it's so broken for stdlib.h to define max, the C standard is very specific about what names are reserved for the application and what names are reserved for standard functions and/or internal use by the implementation. There are very good reasons for this. Defining macro names in system headers that could clash with variable/function names used in the application program is dangerous. In the best case it leads to compile-time errors with an obvious cause, but in other cases it can cause very strange behavior that's hard to debug. In any case it makes it very difficult to write portable code because you never know what names will already be taken by the library.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Removed my answer: yours is best-suited, currently. – San Jacinto Nov 20 '10 at 17:31
  • 6
    @R.. Thanks, but could you please explain why a C library which defines max is broken beyond imagination? – snakile Nov 20 '10 at 17:34
  • 2
    Your comments about why `` should not define `max` are valid up to a point. If the user explicitly requests extra definitions that the implementation provides (for example, by defining `__EXTENSIONS__` (unofficial) or `_POSIX_C_SOURCE` (official)), then it is permissible for `` to provide extra definitions. And on many platforms, the extensions may be enabled by default, and only made unavailable by requesting 'standard conformant mode'. – Jonathan Leffler Nov 20 '10 at 18:12
  • 2
    @Jonathan: it's also true, though, that defining unexpected macros is tougher on programmers than defining unexpected functions. The compiler errors (if any) are less likely to make a whole lot of sense. – Steve Jessop Nov 20 '10 at 21:23
  • Still, the example here (`max`) is very extreme. I would put that just one or two levels of badness below putting `#define i _Complex_I` in a standard header file. Also note that in this case, the only way of disabling the extension is by using another macro in the namespace reserved for the application (`#define NOMINMAX`) which rules out any hope of the implementation being conformant. – R.. GitHub STOP HELPING ICE Nov 20 '10 at 21:23
  • @R: the way to disable the extension is to set an option for the compiler (`/Za`). The `NOMINMAX` configuration macro is for the Windows SDK and is not used by the C runtime library, so is strictly speaking outside the area of library standards conformance (though the extensive use of macros in the Windows SDK can be a real headache at times). – Michael Burr Nov 22 '10 at 20:02
  • Gosh somebody's bitter about the subject! Gave you a vote up anyway. – Scott Sep 29 '11 at 22:21
10

So answering your main question:

Is max(a,b) defined in stdlib.h or not?

No it isn't, it's defined in windef.h around line 187:

#ifndef NOMINMAX

#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif

#endif  /* NOMINMAX */
Calmarius
  • 18,570
  • 18
  • 110
  • 157
4

Protect it with an #ifndef.

#ifndef max
    #define max(a,b) ((a) > (b) ? (a) : (b))
#endif

Keep in mind that the version above is not as safe as an inline function, e.g. max(a++,b--) will cause unxpected results.

John Ledbetter
  • 13,557
  • 1
  • 61
  • 80
0

you can use condition compiling:

#ifndef max
  #define max(a,b) ...
#endif
Vladimir Ivanov
  • 42,730
  • 18
  • 77
  • 103
0

In Visual C++, if you #define NOMINMAX before including the standard headers, you will not get a macro max or min.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • 3
    That's yet another bug. If they'd made it `_NOMINMAX` instead, it would be conformant, but `NOMINMAX` is reserved for the application, and it's nonconformant for the standard library headers to use it for their own purpose. – R.. GitHub STOP HELPING ICE Nov 20 '10 at 17:42