int mystery(int x) {
int mask = x >> 31;
return (x ^ mask)
+ ~mask + 1L;
我相信第一行从x
创建一个掩码,因此如果最高有效位为1,则全为1,如果MSB为0,则全为0。
第二行将掩码与原始x
进行异或,如果掩码为1s,则将翻转所有位;如果掩码为0,则不执行任何操作。
然后第三行添加了掩码的补码,还添加了1L
...这是我不明白的地方。
所以我的问题是,第三行具体是做什么的,特别是1L
?整个功能对x
有什么作用?
这将返回数字的绝对值,而不会在二进制补码机上分支。但是,有一个重要的例外:如果x
最初是INT_MIN
,它将返回INT_MIN
。
让我们以数字-3
为例,并逐步完成此操作。
int mask = x >> 31;
定义了一个名为mask
的变量,该变量为-1
(如果x
最初为负(不是可移植的!)则为所有位,否则为0
。将x
设为-3
[ C0]是mask
。
-1
是(x ^ mask)
的值,如果x
最初为负,则所有位都将翻转。如果x
最初是2
,则此表达式的结果为x
。
-3
如果+ ~mask + 1L;
为负,则将上述结果添加到1
中,否则将x
添加并返回。如果0
最初是3
,则结果为x
。
为了进一步解释此步骤,让我们考虑-3
为-1时。 mask
将所有位翻转为~
。之后,添加0
会导致将1
添加到结果中。
考虑掩码为1
时,0
将所有位翻转到~
(即1
),然后加-1
,所以结果将保持不变。
让我们也逐步完成1
方案:
INT_MIN
是mask
。
将-1
的所有位翻转为INT_MIN
。
将INT_MAX
添加到1
为INT_MAX
(并且行为未定义!!!)。
现在让我们看看正数INT_MIN
会发生什么。以x
为例:
5
是mask
。
0
保持不变。
x
再次保持不变。
除非您使用的是定义所有此行为的编译器,否则将无法使用。我强烈反对使用它。
该函数返回数字的绝对值。
[x
将翻转数字的位,如果(x ^ mask)
全为1(该数字最初为负)。
[mask
将求值为~mask + 1L;
或-1 + 1
,具体取决于0 + 1
分别是全0还是1。
全部放在一起,这意味着当数字为负数时,我们翻转位并加1。当数字为正数时,我们不翻转位并添加0(保持相同)。由于计算机存储负数的方式,因此会将负数转换为正数。您可以通过查找“两个人的赞美”来进一步了解此内容。
假设x是一个32位整数,符号在第32位(最左边),
supposed