2009-07-24 5 views
5

これは、符号付き整数のビット表現に関する疑問です。たとえば、-1を表す場合は、(+1)の2の補数に相当します。したがって、-1は0xFFFFFFFとして表されます。今では31をシフトして結果を印刷すると-1に戻ります。負の数のビット表現

signed int a = -1; 
printf(("The number is %d ",(a>>31));//this prints as -1 

どのようにビットが負の数で表されているか説明してください。

ありがとうございました。

+0

別の角度から見ると:2^Nで割り切れるようにNビット(符号拡張)の右シフトを考えると、DOWN(マイナスの無限大に向かって、0に向かって)に丸めます。拡張)は何回でも-1を生成し続けます。 – vladr

答えて

10

トップビットがゼロの場合、数値は正です。 1のとき、数値は負です。

負の数は右の負の数を維持するために最上位ビットとして「1」にシフト保つシフト。だからあなたはその答えを得ているのです。

より約2の補数の場合は、this Stackoverflow questionを参照してください。


@StoborいくつかのCの実装ではなく1の上位ビットに0をシフトすることができることを指摘[ウィキペディアで確認。] Javaでは、それはdependably算術シフトです。

しかし、質問者によって与えられた出力は、彼のコンパイラが算術シフトを行っていることを示しています。

+0

しかし、それは-1として印刷するshud、それは1儀式として一番上から印刷する必要がありますが、1は負の数を表します。 –

+1

@ Nosredna:また、符号付きビットの動作は実装固有であることにも言及する必要があります。 – Stobor

+0

それは負の数を表しているので、なぜ正の数を出力するのですか? – Nosredna

1

これは符号ビットを保持し、署名された数の仮数部をシフト算術シフト演算です。最上位ビットに

歓声

8

C標準は、それが負の右シフトは、(必ずしも符号付き)か否かを未定義のまま整数(右論理シフト)ゼロをシフトまたはサインビット(算術右シフト)。選択するのは実装次第です。

その結果、移植可能なコードは、それが負の数の上で右シフトを実行しないことを保証します。シフトする前に値を対応する符号なしの値に変換するか(論理シフト右を使用すること、保証されていないビットにゼロを入れることが保証されているか)、値が正であることを保証するか、出力の変化を許容します。

+0

シフト後に最上位ビット(またはビット)に "または"が入る可能性があります。 – Nosredna

+0

ありがとう、私はまだ私のdoyubt yet.Soをクリアしていないすべてのanswers.Guessのために多くのコンパイラやハードウェアですか? –

+2

@Maddy:ハードウェアとコンパイラによって異なります。たとえば、特定のCPUに論理シフト権(LSR)のみがあり、算術シフト権(ASR)がない場合、そのマシンのコンパイラはLSRを使用し、存在しないASRは使用しません。コンパイラにも依存します。マシンにASRとLSRの両方がある場合でも、コンパイラライターは、いくつかの理由のいずれかによって、符号付きおよび符号なしの両方の量に対してLSRを使用することを決定する可能性があります。より速いかもしれません。同じコンパイラも実行される他のプラットフォームと一貫しているかもしれません。コンパイラを書く人がASRを好きではないかもしれません。 –

1

基本的に右シフトには2つのタイプがあります。符号なし右シフトと符号付き右シフト。符号なし右シフトはビットを右にシフトし、最下位ビットを失わせ、最上位ビットを0に置き換えます。符号付き右シフトでは、ビットが右にシフトされ、重要なビットが失われ、最上位のビットが保存される。符号付き右シフトは、2のべき乗(シフトされた場所の数に対応する)で数を除算しますが、符号なしシフトは論理シフト演算です。それが動作するデータ・タイプが符号なしの場合

「>>」演算子は、符号なし右シフトを行い、それが動作しているデータ・タイプが署名されている場合には、符号付き右シフトを行います。だから、あなたがしなければならないことは、目的の結果を得るためにビット操作を実行する前に、オブジェクトを符号なし整数型にキャストすることです。

+0

符号付き整数の場合は必ずしも '符号付きシフト'である必要はありませんが(非常に一般的ですが)、コンパイラやハードウェアによって異なります。 –

+0

うん。そのとおり。私は、x86のいくつかの亜種を実行し、GCCでコンパイルしている、うまく動作するラップトップ/デスクトップ/サーバマシンで長い間プログラミングを行ってきましたが、現在のアプリケーションで想定していることと、保証。 –

0

EDIT:unsigned int型は、少なくとも32ビット幅である

unsigned int a = -1; 
printf(("The number is %d ",(a>>31));//this prints as -1 

場合は、お使いのコンパイラは本当に生産するために許可されていません。以下が書かれたとき、問題のコードは次のように書かれていました-1を出力します(小さな値は、unsigned値をintにキャストしてからprintfに渡す必要があります)。

aは符号なし整数であるため、-1を代入するとUINT_MAX(-1を法とするUINT_MAX + 1に一致する最小の非負の値)を与える必要があります。 unsigned intがプラットフォーム上で少なくとも32ビットを持つ限り、その符号なし量を31右にシフトした結果は、UINT_MAXを2^31で割ったものになります。これはint内に収まる必要があります。 (unsigned intが31ビット以下であれば、シフトの結果が指定されていないため、好きなものを生成することができます)。

関連する問題