这段C代码是什么意思? [短路评估]

What is the meaning of this C code? [short-circuit evaluation]

Jeffrey Stedfast 提出 several functions that calculates the nearest power of 2。其中一个函数的代码如下:

static uint32_t
nearest_pow (uint32_t num)
{
  uint32_t j, k;
  (j = num & 0xFFFF0000) || (j = num); // What is this?
  ...
}

为了完全理解代码,我尝试将行更改为:

  j = num & 0xFFFF0000;
  j = j | (j = num);

一不小心,我得到了正确的结果。但是,当我将这种转换应用于下一行(不包括在我的报价中)时,我得到了错误的结果。原来是我理解错了代码的意思

(j = num & 0xFFFF0000) || (j = num);是什么意思?

实际上,我需要将函数转换为其他编程语言。

(j = num & 0xFFFF0000) || (j = num);

由于逻辑或运算符的短路计算,如果 j = num & 0xFFFF0000 为非 0 (TRUE),则不会计算 j = num;否则,j = num 将在之后进行评估。

因此,整个语义是:

j = num & 0xFFFF0000;
if (j != 0) { // no operation
} else {
    j = num;
}

What is the meaning of (j = num & 0xFFFF0000) || (j = num);?

a || b 形式的内容将计算 a,然后仅当 a 为假时才计算 b。换句话说,只有当 j = num & 0xFFFF0000 为 false 时,才会计算 j = num。如果表达式等于 0,则表达式在 C++ 中被视为假,因此这等同于:

if ((j = num & 0xFFFF0000) == 0) {
    j = num;
}

或者,分解更多可能会使它更清晰:

uint32_t masked = num & 0xFFFF0000;
if (masked == 0) {
    j = num;
} else {
    j = masked;
}

|| 是逻辑或运算符。它具有短路行为,因此如果左侧为真,则不评估右侧(因为逻辑 or 的结果已经从真正的左侧已知为真)。

在这种情况下,如果第一个赋值 j = num & 0xFFFF0000 为零(“false”),则以迂回方式使用它来提供后备赋值 j = num。因此,首先将 num 的高两个字节(掩码 0xFFFF0000)分配给 j。如果这是零(“假”),即高两个字节没有任何 1 位,则 num 被分配给 j.

实际上这意味着“如果它们不为零,则将 num 的高两个字节分配给 j,否则将 num 的低两个字节分配给 j ]”.

(j = num & 0xFFFF0000) || (j = num); 

并且,

j = num & 0xFFFF0000;
j = j | (j = num);

不等价,我不确定为什么你会得到相同的结果。

What is the meaning of (j = num & 0xFFFF0000) || (j = num);?

在讨论它的确切含义之前,您必须了解 logical or || 操作的评估顺序,即从左到右。在 C 中,零 0 表示布尔值 false,任何其他非零值表示布尔值 true。现在看下面的表达式,

left || right

如果lefttrue那么right永远不会被执行,right只有当且仅当left是false时才会执行。

问题仍然存在,在这种情况下 left 将是错误的?在这个表达式中:

(j = num & 0xFFFF0000) || (j = num);

(j = num & 0xFFFF0000) 如果 j 被赋值为 0 则为 false 意味着 num & 0xFFFF0000 产生 0

所以如果 num & 0xFFFF0000 产生 0 那么正确的表达式将执行 (j = num) 并且 j 最后由 num 更新。故事结束。

Now what the following code means?

j = j | (j = num);

意思是,把num赋值给j,然后用前面的j执行bitwise or|,最后的值重新赋值给j .