For getting maximum of two numbers i have following macros
#define max(a,b) ((a) > (b) ? (a) : (b))
#define maxint(a,b) ({int _a = (a), _b = (b); _a > _b ? _a : _b; })
What is the difference between above both. which one is better to use and why. I found these macros' information here. But unable to understand it.
The second macro is safer, but uses a non-standard C extension provided by GCC : statement expressions. But the first expression is "generic". Using the typeof extension of GCC would help:
#define mymax(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); \
_a > _b ? _a : _b; })
To fight against the issue raised in JaredPar's answer you could use preprocessor concatenation and GCC specific __COUNTER__
(or just the more standard __LINE__
), e.g.
#define mymax_counted(a,b,c) ({typeof(a) _a##c = (a); \
typeof(b) _b##c = (b); \
_a##c > _b##c ? _a##c : _b##c; })
#define mymax(a,b) mymax_counted(a,b,__COUNTER__)
but even that is not entirely fail-proof (with bad luck; could collide in some invocation like mymax(_a123,_b123)
if the unique __COUNTER__
happens to be 123 at that time).
Actually, using an inline function is better (because if you call mymaxfun(i++,t[i])
the behavior is well defined and gives the same result as mymaxfun(t[i],i++)
, and because optimizing compilers would produce code as efficient as when using a macro):
static inline int mymaxfun(int a, int b) { return (a>b)?a:b; }
Sadly, C don't have generic functions (consider for that switching to C++ with its templates and use std::max); however C11 has type-generic expressions using the _Generic
keyword
Macros are useful (when mastered), but you should be very careful about side effects in arguments when calling macros (e.g. mymax(i++,t[--i]++)
) so you always should care and document if a name is a macro or something else (like a function). As a rule of thumb avoid side-effects -notably ++
or --
but also many others- in function-call looking expressions (both function calls and macro invocations).
Look at the preprocessor-expanded form of your source code; so for a foo.c
source code, run gcc -C -E foo.c > foo.i
(adding whatever preprocessor options like -I
, -D
etc... are relevant) and look inside foo.i
e.g. with less foo.i
; it is always instructive.
The second macro is safer because it evaluates the inputs exactly once. This is important if the inputs are expressions that have side effects for example
max(i++, --j);
Note that i said safer and not safe. It's still possible for this macro to be incorrect because there could be locals in scope which are already named _a
and _
b. Imagine what would happen if the following was executed
int _a = 42;
int _b = 13;
maxint(_a, _b);
It would expand out to
int _a = 42;
int _b = 13;
{int _a = (_a), _b = (_b); _a > _b ? _a : _b; })
Neither are safe. Please avoid flashy max
macro implementations that rely on non-standard C extensions like expression statements which will give you all sort of headaches if you ever have to port your code to a different platform. Doing my best to present this answer from becoming a rant, the max
macro is, in my opinion, one of the worst things in C standard libraries due to its potential side-effects. In times past, I've #undef
ed max
just to be on the safe side.
Your're better off coding the second macro maxint
as a function as it has all the drawbacks of macros (e.g. can't debug easily, instantiated variables clashing with locals) but none of the benefits (e.g. genericisation).
Alternatives:
My favourite: use the ternary inline: a > b ? a : b
where you can drop the parentheses to taste since you know exactly what is going on. It will also be faster than macros that try to be safe by taking value copies.
Build your own functions. Consider defining max
for integral types and fmax
for floating point. There is already a precedent here with abs
and fabs
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With