3

実行しているいくつかの計算用にビットマスクを生成しています。ここでは、右端のxビットを除くすべてがゼロになるようにintをマスクする必要があります。私はこれを使用して行います:

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(または、sの場合は64)によって変更されます。

JLS 15.19

左側のオペランドのプロモートされたタイプがintの場合、右側のオペランドの下位5ビットのみがシフト距離として使用されます。これは、右側のオペランドに、マスク値0x1f(0b11111)を使用したビット単位の論理AND演算子&(§15.22.1)が適用されたかのようです。したがって、実際に使用されるシフト距離は、常に0〜31の範囲になります。

左側のオペランドのプロモートされたタイプが長い場合、右側のオペランドの下位6ビットのみがシフト距離として使用されます。これは、右側のオペランドに、マスク値0x3f(0b111111)を使用したビット単位の論理AND演算子&(§15.22.1)が適用されたかのようです。したがって、実際に使用されるシフト距離は、常に0〜63の範囲になります。

Javaがこの動作を選択した理由については、アドバイスはありません。

于 2012-08-16T21:34:52.670 に答える