这个min()函数是如何工作的

How does this min() function work?

本文关键字:工作 何工作 min 函数 这个      更新时间:2023-10-16

我遇到了这个代码:

int __min(int a, int b) {
    return ((a)-(((a)-(b))&((b)-(a))>>31));
}

我可以想象它与2s补码有关,它只适用于有符号的32位整数,但在那之后我就迷失了方向。

我发现了这个问题,但我不认为这些功能是相关的,还是我错了?

所以我有两个问题:

  1. 为什么这个功能有效
  2. 有没有(a<b)?a:b不起作用,而这个函数会起作用,或者这个函数只是为了好玩而过于复杂

编辑:该函数是为GPU编写的,所以我认为@Banex这样编写它的目的可能是为了避免分支。

这是为32位有符号值设计的。让我们一步一步地把它分解。

((b)-(a))>>31)

右移运算符基本上取32位值中的最高位,并将其符号扩展到剩余的31位。这就是右移运算符处理带符号值的方式。

如果b大于a,则减法的结果将为正,最高位将为0,并且其结果为0。

如果b小于a,则减法的结果将为负,最高位将为1,并且减法的结果为-1。最高的比特被向下移位到所有剩余的比特。将设置32位值中的所有位,即-1。

您可以通过编写一个短程序来验证这一点,该程序将正值或负值放入32位的int中,并将其右移31位;则观察到结果将是0或-1。如您所知,在二进制补码运算中,值-1的所有位都已设置。

((a)-(b)) & (0 or -1, as the result of the previous operation).

因此,如果b小于a,则右侧值设置了所有位,并且逐位&运算符的结果是左侧值。或CCD_ 11。

如果b大于a,则右侧的值具有所有比特0,并且&的结果为0。

结论:

如果b小于a,则上述表达式的计算结果为:

a-(a-b)
or
a-a+b
or
b

如果b大于a,则表达式的结果为

a - 0
or
a

表达式

((a)-(b))&((b)-(a))>>31

即没有大多数多余的括号

(a - b) & (b - a) >> 31

评估为

a - b

如果a>b,则返回

0

否则,如果它最终从a中减去,它与相同

if (a > b)
   return (a - (a - b));
else
   return (a - 0);