C Macro for minimum of two numbers

痴心易碎 提交于 2019-12-10 14:43:28

问题


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.


回答1:


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.




回答2:


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.
*/



回答3:


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.




回答4:


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; }



回答5:


I think this method is rather cute:

#define min(a, b) (((a) + (b) - fabs((a) - (b))) * 0.5)




回答6:


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.




回答7:


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.



来源:https://stackoverflow.com/questions/2458723/c-macro-for-minimum-of-two-numbers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!