C 宏,求两个数中的最小值

发布于 2024-08-25 18:35:22 字数 88 浏览 6 评论 0原文

我想用 #define 创建一个简单的宏来返回两个数字中较小的一个。

我怎样才能在 C 中做到这一点?提出一些想法,看看是否可以让它变得更加混乱。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

二智少女猫性小仙女 2024-09-01 18:35:22

通常:

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

请注意,这会评估最小值两次,这是 中发生灾难的原因最近的问题

但你为什么要混淆它呢?


该函数将结果存储在变量中,并且仅对每个参数求值一次。它基本上是一个穷人的内联函数+声明:

#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_ ; \
            }

使用它如下:

min(int, x, 3, 4)
/* x is an int, equal to 3
  Just like doing:

  int x = min(3, 4);

  Without double evaluation.
*/

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.
*/
抚笙 2024-09-01 18:35:22

而且,只是为了它的地狱,一个 GNU C 示例:

#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_; \
    })

它没有混淆,但我认为这适用于任何类型、任何上下文、(几乎,请参阅注释)任何参数等;如果您能想到任何反例,请纠正。

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.

梦冥 2024-09-01 18:35:22

当然,您可以为此使用#define,但为什么要这样做呢?使用 #define 的问题是,即使使用括号,您也会使用这样的代码得到意外的结果(好吧,您实际上不会这样做,但它说明了问题)。

int result = min(a++, b++);

如果您使用的是 C++ 而不是 C,那么使用内联函数肯定更好,它 (i) 避免多次评估参数,并且 (ii) 是类型安全的(您甚至可以提供采用其他类型值的版本,例如无符号、双精度或字符串)。

inline int min(int a, int b) { return (a < b) ? a : b; }

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; }
清浅ˋ旧时光 2024-09-01 18:35:22

我认为这个方法相当可爱:

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

I think this method is rather cute:

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

爱的故事 2024-09-01 18:35:22

我想用 #define 创建一个简单的宏,用于返回两个数字中较小的一个。

我想在数字浮点时添加解决方案。


考虑一下当数字是浮点数并且其中一个数字是非数字时。那么a <的结果是无论另一个数字的值如何,b 始终为 false

// the result is `b` when either a or b is NaN
#define min(a, b) (((a) < (b)) ? (a) : (b))

可能希望结果如下所示,其中“NaN 参数被视为缺失数据”。 C11 脚注 #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

要使用 C 中的宏来执行此操作,只需包装支持上表的 fmin() 函数。当然,代码通常应该直接使用 fmin() 函数。

#include <math.h>
#define my_fmin(a, b) (fmin((a), (b))

请注意,fmin(0.0, -0.0) 可能返回 0.0-0.0。它们都有相同的价值

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.

握住你手 2024-09-01 18:35:22

如果我只是想稍微混淆一下这一点,我可能会选择这样的内容:

#define min(a,b) ((a) + ((b) < (a) ? (b) - (a) : 0))

我认为 Doynax 的解决方案也非常可爱。对于多次评估宏参数的通常保留。

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.

梦一生花开无言 2024-09-01 18:35:22

对于稍微混淆的情况,请尝试以下操作:

#define MIN(a,b)  ((((a)-(b))&0x80000000) >> 31)? (a) : (b)

基本上,它将它们相减,并将符号位视为 1 或 0。
如果减法结果为负数,则第一个参数较小。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文