2009-06-21 7 views
8

私は(それに鉱山を統合する前に慎重に)FindBugsのを使用して、サードパーティのソースコードをスキャンし、次の警告が見出された:Findbugs警告:32分の1の整数シフト - それはどういう意味ですか?

long a = b << 32 | c 

バグ:32パターンIDによって整数シフト: ICAST_BAD_SHIFT_AMOUNTを、タイプ:BSHIFT、 カテゴリ:正確

コード範囲 0..31外一定量整数シフトを行います。これの効果は、整数値 の下位5ビットを使用してシフトする量を決定することです。この はおそらく期待されていませんでしたが、 少なくとも混乱しています。

誰でも上記の意味を正確に説明できますか?

ありがとうございます! (私はJavaプログラミングではかなり初心者です)

答えて

30

左オペランドの促進タイプがintである場合は、右側のオペランドの5つだけ最下位ビットがシフト距離として使用されます。これは、右側のオペランドがマスク値0x1fのビット論理AND演算子&(15.22.1)を受けたかのようです。したがって実際に使用されるシフト距離は常に0〜31の範囲です。

だから、bがint型である場合、式は、私は非常に疑問に意図されたものである

long a = b | c; 

と同じです。おそらくそうだったはずです

long a = ((long) b << 32) | c; 

(bがすでに長い場合、コードは正しく、FindBugsはバグについて間違っています)。

+0

)「int >> 32(0x100000)== int >> 0(0x00000) '? –

+1

あなたが使っている奇妙な擬似構文ですが、そうです。 – UndefinedBehavior

5

編集:ほぼ確実に問題は「b」が「INT」と「長い」ではないという事実から生じます。

「b」が長整数ではなく整数で、左に32ビットシフトした場合、は元の値からのすべてのビットが削除されているため、式全体の結果は次のようになります。 'c'あなたは定義されていない振る舞いを呼び出すので、どんな結果も許されます。 Javaは、Rasmus Faberのコメントと選択された解答に記載されているように、さまざまなことを定義しています。シフト可能な最大ビット数をモジュロシフトしています。 [それはビジネスを行うには奇妙な方法だと思われる。私はおそらくそれらを持っている言語で例外のために準備していただろう。しかし、明確に定義されています。これは、定義が正確であるよりも重要です。式が評価されている間は、64ビットへの変換は行われません。式が完了し、代入が行われたときに発生します。

5ビットへの参照は興味深いです。つまり、左にシフトすると、たとえば48、またはバイナリ110000の場合は、左に16シフトする場合と同じです。または、「x << n」は「x << (n % 32)」と同じです。 Java Language Specificationから

+1

D'oh、あなたが正しいです、私の答えを削除し、あなたをアップモード: –

+1

あなたの答えの最初の部分が間違っています。 Javeでは、b << 32はbであり、ゼロではない。しかし、2番目のパラグラフは正しいです。 –

+1

修正:範囲外の引数[0、typewidth - 1]で値をシフトするとき、Cの振る舞いは_undefined_です。たとえば、nvidiaとintelのopenclコンパイラでは、 'b >> 32'という表現の動作が異なります。 – notso

関連する問題