热门问题的答案让轮班操作员错了?
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 位,并且右移是算术运算,所以是的实现定义但很常见),那么我们将有 0x00000000
当 data[c] >= 128
或 0xffffffff
当 data[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
的值而不进行分支。
在下面的问题中: 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 位,并且右移是算术运算,所以是的实现定义但很常见),那么我们将有 0x00000000
当 data[c] >= 128
或 0xffffffff
当 data[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
的值而不进行分支。