热门问题的答案让轮班操作员错了?

Top question`s answer gets shift operator wrong?

在下面的问题中: Why is processing a sorted array faster than processing an unsorted array? 接受的答案解释了一种避免给定示例进行分支预测的方法。 He/she 继续用一些按位运算符替换条件语句:

Replace:

if (data[c] >= 128)
    sum += data[c];

with:

int t = (data[c] - 128) >> 31;
sum += ~t & data[c];

然而,在他向右移动的行中,他似乎是在一个可能有符号的值上这样做,根据这个:

If the value after the shift operator is greater than the number of bits in the left-hand operand, the result is undefined. If the left-hand operand is unsigned, the right shift is a logical shift so the upper bits will be filled with zeros. If the left-hand operand is signed, the right shift may or may not be a logical shift (that is, the behavior is undefined).

是未定义的行为。有人可以澄清我是否遗漏了他正在执行的按位运算的某些内容,并且还可以用外行的术语解释执行的按位运算的目的是什么(假设我们将它们解释为某些带符号值的移位定义中的已定义行为)。

如果data[c] >= 128,则data[c] - 128为非负数,所以符号位为0。否则,如果 data[c] < 128,则 data[c] - 128 将为负数,因此其符号位将为 1.

如果我们右移 31(假设 int 是 32 位,并且右移是算术运算,所以是的实现定义但很常见),那么我们将有 0x00000000data[c] >= 1280xffffffffdata[c] < 128.

如果我们然后按位反转该值,那么当 data[c] >= 128 时我们将得到 0xffffffff 或当 data[c] < 128 时得到 0x00000000

如果我们将该值与 data[c] 按位 AND,那么当 data[c] >= 128 时我们将得到 data[c] 或当 data[c] < 128 时得到 0x00000000

0 添加到 sum 没有任何作用,因此我们实际上只添加大于或等于 128 的值而不进行分支。