A Safe Solution to the Max Macro? - c

We all know this famous macro example:
#define max(a,b) ((a) > (b) ? (a) : (b))
And, since it uses a and b twice, it becomes inaccurate when we do something like:
max(x, y++); // because this gets translated to...
((x) > (y++) ? (x) : (y++)); // y is incremented twice
In Effective C++, Scott Meyers presents a C++ solution to this, using inline functions.
In 21st Century C, I was hoping for a similar C solution, but sadly all it advised was to avoid double usage. That made me sad. :'(
Of course, one can always replace it with a regular function. But I was wondering whether there is a C-only macro solution to this, that solves the double usage problem. Any possible solution?

In case of GCC you can use typeof extension, like this:
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })

To your relief C has inline functions since C99.

Related

What does parentheses mean in typeof in C? [duplicate]

This question already has answers here:
The need for parentheses in macros in C [duplicate]
(8 answers)
Closed 4 years ago.
I am studying the Linux container_of function and I find the use of parentheses of typeof is really confusing.
Here is the code of the function container_of:
#define container_of(ptr, type, member) ({ \
const typeof( ((type*)0)->member) * __mptr =(ptr);\
(type*)( (char*)__mptr - offsetof(type,member) );})
At the second line, we have
const typeof( ((type*)0)->member) * __mptr =(ptr);
I do not understand why we use parentheses on the right side.
I search it online and find some similar usage. For example, from https://gcc.gnu.org/onlinedocs/gcc/Typeof.html , I found a function max(a,b)
#define max(a,b)
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
In this case, we do have similar usage typeof (a) _a = (a);
Why should we use parentheses on the right side? Can we remove the parentheses on the right side to make it typeof (a) _a = a;?
Thanks in advance!
Macros created via #define perform direct token substitution. Because of this, using parenthesis around the arguments of a function-like macro is good practice as it prevents unexpected issues from occurring.
For example:
#define multiply(x, y) x * y
If you were to use this macro here:
int z = multiply(1 + 3, 4 + 5) / 3;
You might expect z to contain the value 12, but you would be mistaken.
It would expand the above to:
int z = 1 + 3 * 4 + 5 / 3;
Which would result in 14. Using parenthesis avoids this issue. If it was instead defined as:
#define multiply(x, y) ((x) * (y))
Then the above example would expand to:
int z = ((1 + 3) * (4 + 5)) / 3;
Which would give the expected result.
We do not know argument will be used for ptr when the container_of macro is used. It might be an identifier name like MyPointer. But it might be an expression, like MyArray + 3.
Common practice in macros is to use parentheses around parameters in the replacement list. For example, if we define square:
#define square(x) ((x) * (x))
Then square(3+4) will be replaced with ((3+4) * (3+4)), which is 49 as desired. If we had instead used:
#define square(x) (x * x)
then square(3+4) would be replaced with (3+4 * 3+4), which would be evaluated as 3 + 4*3 + 4, which is 3 + 12 + 4, which is 19, which is not desired.
Similarly, in the code you show, const typeof( ((type*)0)->member) * __mptr =(ptr);, ptr is being used to initialize a newly defined object named __mptr. It is in parentheses just for safety. It does not change how the typeof operates.
You should not remove these parentheses. In this particular context, there is not much that would normally be passed for ptr that would break the macro without the parentheses, but there are some expressions that are theoretically possible that could break it.

what is the difference of these two macro max?

writing leetcode
I use the macro like this:
#define max(a,b) ((a) > (b))?(a):(b)
it is wrong,when i change the macro like this,it's right
#define max(a,b) (((a) > (b))?(a):(b))
can't figure out why does this different.Here is the code,you can check it out.
#define UNBALANCED 99
#define max(a,b) (((a) > (b))?(a):(b))
int getHeight(struct TreeNode * root)
{
if(NULL == root)
return -1;
int l = getHeight(root->left);
int r = getHeight(root->right);
if(UNBALANCED == l || UNBALANCED == r || abs(l-r) > 1)
return UNBALANCED;
return 1 + max(l,r);
}
bool isBalanced(struct TreeNode* root)
{
if(NULL == root)
return true;
return getHeight(root) != UNBALANCED;
}
that is different with The need for parentheses in macros in C
The former fails to isolate the macro replacement from neighboring operands. For example:
1 + max(a, b)
expands to:
1 + ((a) > (b))?(a):(b)
and that groups as:
(1 + ((a) > (b))) ? (a) : (b)
Then (1 + ((a) > (b))) is always nonzero, so (a) is always chosen.
To prevent this, a macro that expands to an expression should use parenthesis around its entire expression to prevent its parts from grouping with neighboring operands.
The second version of your macro has extra parentheses which make the expression ((a) > (b))?(a):(b) evaluated as a whole. More code would be needed to explain exactly why the first one is wrong in your case. Also, see this.
Arguably both of them are incorrect; what if you wanted to use your macro like:
MAX(i++, j++)
The resulting ternary-operator expression from your examples cause whichever expression is smaller to be evaluated twice. Yowch! Since you (and most future readers) likely use GCC or clang, here's a better example with some compiler extensions (__typeof__ and statement expressions) that both of them support.
#define MAX(a, b) ({ __typeof__ (a) a__ = (a); \
__typeof__ (b) b__ = (b); \
(a__ > b__) ? a__ : b__; })

find min(a,b,c) or max(a,b,c) with using #define macro preprocessor in c

this is the question what asked in my exam is: "write cource code of min(a,b,c) with macros in c language."
#define min(a,b,c) ((a)<(b)?((a)<(c)?(a):(c)):((b)<(c)?(b):(c)))
is there better way to solve min/max(x,y,z) problem?
Your solution, and all portable macro-based ones, are a good reason why the use of macros should be limited as much as possible. Nowadays, I pretty much use them for little more than conditional compilation.
In terms of defining constants, you are better off with enumerations.
In terms of function-like macros, you're far better off using functions which you can suggest to the compiler to be made inline, or just rely on the compiler to figure that out (they're usually pretty good at that).
The reason why function-like macros are a bad idea is because, being simple text substitution, the sequence:
#define mymax(a, b) (a) > (b) ? (a) : (b)
int x = mymax(y++, complexFunction());
will actually evaluate y++ and/or call complexFunction() more than once, something a real function would not do.
By all means use them provided you understand the limitations. Me, I'll rely on the compiler doing the right thing for functions so that I don't have to worry about the dark corners of C too much :-)
Yes. Write functions.
int min2( int x, int y ) { return x < y ? x : y; }
int min3( int x, int y, int z ) { return min2( x, min2( y, z ) ); }
If you wish for pretty, you can write some variadic macros that choose the correct function based on the number of arguments. Those are a bear to write, though.
If you wish to stick with only macros, your choices are much less friendly. Ajay B’s solution (fixed as per commentary) works well.
GCC supports some nice extensions that eliminate re-evaluation issues:
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
You can then easily write any n-ary macro you wish that does not suffer from parenthetical or re-evaluation horrors.
#define max3(a,b,c) max(a,max(b,c))
I think the key point you missed in the question is "macros" not and macro. You can simplify this a lot if you break it down further as follows -
#define min2(a, b) ((a) < (b) ? (a) : (b))
#define min(a, b, c) (min2(min2((a), (b)), (c)))
This is also much easier to comprehend.

The best way to define a "between" macro in C

What's the best way to define a between macro, which is type generic (char,int,long)
which will return true if a number is between to other numbers inputted.
I'm tried to google it, but I didn't find anything.
Edit: The order of the two boundaries given shouldn't matter. so it can be more general.
If you do something like:
#define BETWEEN(a, b, c) (((a) >= (b)) && ((a) <= (c)))
you are going to have problem with the double evaluation of a. Think what would happens if you do that with a functions that has side effects...
you should instead do something like:
#define BETWEEN(a, b, c) ({ __typeof__ (a) __a = (a); ((__a) >= (b) && ((__a) <= (c)) })
(edited because the result should not depend of the order of b and c):
#define BETWEEN(a, b, c) \
({ __typeof__ (a) __a = (a);\
__typeof__ (b) __b = (b);\
__typeof__ (c) __c = (c);\
(__a >= __b && __a <= __c)||\
(__a >= __c && __a <= __b)})
Firstly, don't use macros for things like this - use functions (possibly inline).
Secondly, if you must use macros, then what's wrong with e.g.
#define BETWEEN(x, x_min, x_max) ((x) > (x_min) && (x) < (x_max))
?
As per your subsequent edit, if you don't know the ordering of x_min and x_max then you could do this:
#define BETWEEN2(x, x0, x1) (BETWEEN((x), (x0), (x1)) || \
BETWEEN((x), (x1), (x0)))
The usual caveats about macros and side-effects etc apply.
Edit: removed space between macro & arguments for compilation
If all types are the same, how about:
/* Check if 'a' is between 'b' and 'c') */
#define BETWEEN(a, b, c) (((a) >= (b)) && ((a) <= (c)))
Note that if the types of a, b and c above are different, the implicit type conversions of C might make it wrong. Especially if you mix signed and unsigned numbers.
+1: A not-so-trivial question, since it involves the problem of the evaluation of macro parameters. The naive solution would be
#define BETWEEN(x,l1,l2) (((x) >= (l1)) && ((x) <= (l2)))
but "x" is evaluated twice, so there may be problems if the expression has side effects. Let's try something smarter:
#define BETWEEN(x,l1,l2) (((unsigned long)((x)-(l1))) <= (l2))
Very very tricky and not so clean, but...
#define BETWEEN_MIN(a, b) ((a)<(b) ? (a) : (b))
#define BETWEEN_MAX(a, b) ((a)>(b) ? (a) : (b))
#define BETWEEN_REAL(val, lo, hi) (((lo) <= (val)) && ((val) <= (hi)))
#define BETWEEN(val, hi, lo) \
BETWEEN_REAL((val), BETWEEN_MIN((hi), (lo)), BETWEEN_MAX((hi), (lo)))
See code running: http://ideone.com/Hb1vP
If I understand correctly, you will need 3 numbers, the upper limit, the lower limit and the number you're checking, so I would do it like this:
#define BETWEEN(up, low, n) ((n) <= (up) && (n) >= (low))
This assumes the between is inclusive of the upper and lower limits, otherwise:
#define BETWEEN(up, low, n) ((n) < (up) && (n) > (low))

C Macro for minimum of two numbers

I want to make a simple macro with #define for returning the smaller of two numbers.
How can i do this in C ? Suggest some ideas, and see if you can make it more obfuscated too.
Typically:
#define min(a, b) (((a) < (b)) ? (a) : (b))
Be warned this evaluates the minimum twice, which was the reason for disaster in a recent question.
But why would you want to obfuscate it?
This one stores the result in a variable, and only evaluates each argument once. It's basically a poor-mans inline function + declaration:
#define min(t, x, a, b) \
t x; \
{ \
t _this_is_a_unique_name_dont_use_it_plz_0_ = a; \
t _this_is_a_unique_name_dont_use_it_plz_1_ = b; \
x = _this_is_a_unique_name_dont_use_it_plz_0_ < \
_this_is_a_unique_name_dont_use_it_plz_1_ ? \
_this_is_a_unique_name_dont_use_it_plz_0_ : \
_this_is_a_unique_name_dont_use_it_plz_1_ ; \
}
Use it like:
min(int, x, 3, 4)
/* x is an int, equal to 3
Just like doing:
int x = min(3, 4);
Without double evaluation.
*/
And, just for the hell of it, a GNU C example:
#define MAX(a,b) ({ \
typeof(a) _a_temp_; \
typeof(b) _b_temp_; \
_a_temp_ = (a); \
_b_temp_ = (b); \
_a_temp_ = _a_temp_ < _b_temp_ ? _b_temp_ : _a_temp_; \
})
It's not obfuscated, but I think this works for any type, in any context, on (almost, see comments) any arguments, etc; please correct if you can think of any counterexamples.
Sure, you can use a #define for this, but why would you want to? The problem with using #define, even with parentheses, is that you get unexpected results with code like this (okay, you wouldn't actually do this, but it illustrates the problem).
int result = min(a++, b++);
If you're using C++ not C, surely better to use an inline function, which (i) avoids evaluating the parameters more than once, and (ii) is type safe (you can even provide versions taking other types of value, like unsigned, double or string).
inline int min(int a, int b) { return (a < b) ? a : b; }
I think this method is rather cute:
#define min(a, b) (((a) + (b) - fabs((a) - (b))) * 0.5)
I want to make a simple macro with #define for returning the smaller of two numbers.
I wanted to add a solution when the numbers are floating point.
Consider when the numbers are floating point numbers and one of the numbers is not-a-number. Then the result of a < b is always false regardless of the value of the other number.
// the result is `b` when either a or b is NaN
#define min(a, b) (((a) < (b)) ? (a) : (b))
It can be desirable that the result is as below where "NaN arguments are treated as missing data". C11 Footnote #242
a NaN | b NaN | a < b | min
-------+---------+---------+---------------
No | No | No | b
No | No | Yes | a
No | Yes | . | a
Yes | No | . | b
Yes | Yes | . | either a or b
To do so with a macro in C would simple wrap the fmin() function which supprts the above table. Of course code should normally used the fmin() function directly.
#include <math.h>
#define my_fmin(a, b) (fmin((a), (b))
Note that fmin(0.0, -0.0) may return 0.0 or -0.0. They both have equal value.
If I were just trying to lightly obfuscate this I would probably go with something like:
#define min(a,b) ((a) + ((b) < (a) ? (b) - (a) : 0))
I think Doynax's solution is pretty cute, too. Usual reservations for both about macro arguments being evaluated more than once.
For slightly obfuscated, try this:
#define MIN(a,b) ((((a)-(b))&0x80000000) >> 31)? (a) : (b)
Basically, it subtracts them, and looks at the sign-bit as a 1-or-0.
If the subtraction results in a negative number, the first parameter is smaller.

Resources