3

我正在为我正在做的一些计算生成位掩码,我需要屏蔽一个 int 以便除 x 最右边的位之外的所有位都变为零。我这样做使用:

int mask = ~(-1 << x);

这适用于除 x = 32 之外的所有 x 值。它应该返回 -1,但它返回 0。这里发生了什么?

另外,我试过这个:

int mask = -1 >>> 32 - x;

在 x = 0 它应该返回 0,但它返回 -1。不知何故,将某些东西移动 32 会导致操作返回运算符的左侧。当我尝试将 -1 移动 33 或 34 位时,它会返回一个值,就好像它移动了 1 或 2 一样。我假设 Java 实际上做了这样的事情是否正确:

int mask = ~(-1 << x % 32);

int mask = -1 >>> (32 - x) % 32;

?

如果是这样,如果超过 int 的 32 位长度,为什么要围绕行为进行这种循环?Oracle 上的文档明确指出:

无符号右移运算符“>>>”将零移到最左边的位置

但很明显,当它必须移动超过 32 倍时,它实际上并没有这样做......

4

1 回答 1

8

是的,你是对的;班次long在应用之前被修改了 32(或 64,对于 s)。

JLS 15.19

如果左侧操作数的提升类型是 int,则只有右侧操作数的五个最低位用作移位距离。就好像右手操作数受到按位逻辑与运算符 & (§15.22.1) 的影响,掩码值为 0x1f (0b11111)。因此,实际使用的移动距离总是在 0 到 31 的范围内,包括 0 到 31。

如果左手操作数的提升类型是长的,那么只有右手操作数的六个最低位被用作移位距离。就好像右手操作数经过位逻辑与运算符 & (§15.22.1) 与掩码值 0x3f (0b111111)。因此,实际使用的移位距离总是在 0 到 63 的范围内,包括 0 到 63。

至于Java为什么选择这种行为,我对你没有任何建议。

于 2012-08-16T21:34:52.670 回答