web-dev-qa-db-ja.com

あなたはビットごとの右シフトがCを埋めるのを制御できますか?

私が知る限り、Cで左シフトビット演算子を使用すると、空のビットが0で埋められることが保証されます。ただし、右シフトは実装に依存することを読んだことがあります。つまり、一部のマシンでは、空のビットが0で埋められたり、1で埋められたりします。

私はプログラムで右シフトを使用しており、実際、私のマシンは空のビットを1で埋めています。問題は、代わりに0で埋める必要があることです。

右シフトで0を強制的に使用する方法はありますか?

1つの解決策は、右シフトが適用された後、011111111のようなマスクを作成し、ビットごとのANDを適用することです。これにより、挿入された左端の1が0に変更されます。

しかし、これは面倒で時間を浪費します。私のマシンに右シフトを1で埋めるように伝える方法があれば、はるかに簡単です。

ありがとう

28
Daniel Scocco

数値をunsignedにキャストしてからシフトします。それは強制的に0を埋めます。

39
dan04

いいえ、できません。

符号なしの型のシフトは明確に定義されており(右のオペランドが負ではなく、左のオペランドの幅より小さい場合)、常にゼロで埋められます。

符号付きの型でのシフト(またはビット単位の演算)は、通常はお勧めできません。左のオペランドが負の場合、<<には未定義の動作があり、>>は、実装で定義された結果を生成します(つまり、コンパイラーはその動作を文書化する必要がありますが、それを制御する方法はありません)。符号付きタイプの負でない値の場合、結果は期待どおりです-オーバーフローしない限り(オーバーフローする場合の動作は未定義です)。

C99標準 の内容は次のとおりです(セクション6.5.7)。

整数の昇格は、各オペランドで実行されます。結果のタイプは、プロモートされた左オペランドのタイプです。右のオペランドの値が負であるか、プロモートされた左のオペランドの幅以上である場合、動作は未定義です。

E1<<E2の結果はE1左シフトE2ビット位置;空のビットはゼロで埋められます。 E1が符号なしの型である場合、結果の値はE1になります。 ×2E2、結果の型で表現可能な最大値より1を法として減じられます。 E1に符号付きの型と負でない値があり、E1×2の場合E2 結果タイプで表現できる場合、それが結果の値になります。それ以外の場合、動作は未定義です。

E1>>E2の結果はE1右シフトE2ビット位置。 E1に符号なしの型がある場合、またはE1に符号付きの型があり、非負の値、結果の値はE1/ 2の商の整数部E2E1に符号付きの型と負の値がある場合、結果の値は実装定義です。

17
Keith Thompson

算術演算と論理演算の2つの異なる右シフト演算があります。

論理シフトは、Cの符号なし数値で使用されます。これは、常に上位ビットをゼロで埋めます。これが必要です。

算術シフトは、シフトされる数値の符号を保持するため、符号付き数値で使用されます。数値が正の場合、最上位ビットは0になり、0で埋められます。数値が負の場合、最上位ビットは1になるため、1で埋められます。

Javaでは、これらは実際には異なる演算子を使用することに注意してください:>>算術、>>>は論理です。 Javaには符号なしの型がないため、これが必要です。

5
Jay Conrod