这三行C代码本身是做什么的,它们总共做什么?

问题描述 投票:1回答:4
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有什么作用?

c
4个回答
2
投票

这将返回数字的绝对值,而不会在二进制补码机上分支。但是,有一个重要的例外:如果x最初是INT_MIN,它将返回INT_MIN

让我们以数字-3为例,并逐步完成此操作。

  1. int mask = x >> 31;定义了一个名为mask的变量,该变量为-1(如果x最初为负(不是可移植的!)则为所有位,否则为0。将x设为-3 [ C0]是mask

  2. -1(x ^ mask)的值,如果x最初为负,则所有位都将翻转。如果x最初是2,则此表达式的结果为x

  3. -3如果+ ~mask + 1L;为负,则将上述结果添加到1中,否则将x添加并返回。如果0最初是3,则结果为x

    为了进一步解释此步骤,让我们考虑-3为-1时。 mask将所有位翻转为~。之后,添加0会导致将1添加到结果中。

    考虑掩码为1时,0将所有位翻转到~(即1),然后加-1,所以结果将保持不变。

让我们也逐步完成1方案:

  1. INT_MINmask

  2. -1的所有位翻转为INT_MIN

  3. INT_MAX添加到1INT_MAX(并且行为未定义!!!)。

现在让我们看看正数INT_MIN会发生什么。以x为例:

  1. 5mask

  2. 0保持不变。

  3. x再次保持不变。

除非您使用的是定义所有此行为的编译器,否则将无法使用。我强烈反对使用它。


0
投票

该函数返回数字的绝对值。

[x将翻转数字的位,如果(x ^ mask)全为1(该数字最初为负)。

[mask将求值为~mask + 1L;-1 + 1,具体取决于0 + 1分别是全0还是1。

全部放在一起,这意味着当数字为负数时,我们翻转位并加1。当数字为正数时,我们不翻转位并添加0(保持相同)。由于计算机存储负数的方式,因此会将负数转换为正数。您可以通过查找“两个人的赞美”来进一步了解此内容。


0
投票

假设x是一个32位整数,符号在第32位(最左边),


0
投票
我相信返回其参数的绝对值是

supposed

© www.soinside.com 2019 - 2024. All rights reserved.