1


0

符号付き整数に対応するビットパターンが右にシフトされると

1空きビットは符号ビットで埋められます2空きビットは0で埋められます3結果は実装に依存します4上記のどれも

この質問に対する答えは3番目の選択肢です.. 誰もがこれを説明できますか、、

また、Cプログラミングにおける左シフト演算子と右シフト演算子の背後にある理論について、いくつかの基本的な考え方を説明します。 例えば。

いずれかの操作が実行されたときに空のビットに書き込まれるもの。 私は、左シフトが空のビットを0で埋め、右シフトが1を満たすことを確認しました。 ロジックをクリアしてください。

5 Answer


5


Cは、符号ビット、または整数のビットレベル表現について何かがあることを保証していません。

http://en.wikipedia.org/wiki/Two%27s_complement[2の補数]については、通常、符号ビットがシフトインされるのがわかりますが、それは実装次第です。


5


私は、実装に依存しているのは正確かという問題について、仕様をチェックする必要があります。 しかし、私が(混乱した)長年の組み込みシステムプロジェクトで使用したすべての実装は賢明です。

  • 左シフトは常に下位ビットで0をシフトインします。 他の価値はありません センス。

  • 右シフトはデータ型によって異なります。 署名の右シフト integerは、残りを右にシフトするときに上位ビットを複製します。 これは「算術シフト」と呼ばれ、元の数の符号を保持しながら値を2で除算するという優れた特性(少なくとも2の補数算術)を持っています。 符号なし整数の右シフトは、0を上位ビットにシフトします。通常、これは「論理シフト」として知られています。

どちらも有用であるため、実装で両方の種類のシフトを提供することは理にかなっています。どちらを意味するかを選択するために符号付き/符号なしを使用することは賢明な選択です。

*編集:*絶対に実装に依存していることの少なくとも1つのことは、C標準が(完全に)整数の基礎となる実装とその記憶領域を指定していないということです。 たとえば、補数演算を使用するマシン用に準拠したCコンパイラを構築することが可能です。 ネイティブストレージがマグニチュードBCDに署名されているマシン用に準拠コンパイラを構築することも可能です(私は思います)。 (いいえ、私は間違っていました。下記参照)

実際には、世界はCPUのための2の補数バイナリにほぼ定まっており、いくつかの小学校は議論されています。

そのため、疑問の一部は、実際にどのように[および]演算子の意味を、使用する基礎となる算術システムに関係なく安定した方法で定義するにはどうすればよいのかということです。

IIRCでは、「n << 1」の定義は事実上「n * 2」であり、「n >> 1」は事実上「n / 2」であり、1を超えてシフトするという自然な拡張を伴う(ただし31以下) …​ 未定義のドラゴンがあります…​)そして `>>`演算子は符号付きの値を操作した場合に符号を保存するという概念を持ちます。

編集2: Pete Kirkhamは、C規格では、符号付きマグニチュードか10の補数かにかかわらず、整数のBCD表現の怖いケースは特に許可されていないとの彼のすばらしい答えで指摘しています。 Knuthが初期のhttp://www-cs-faculty.stanford.edu/~knuth/taocp.htmlのサンプルコードに(オプションで)BCDマシンを使っていたとしても、それは良いことだと私は確信しています。コンピュータプログラミングの芸術]。

BCDが正しい答えであるようなまれな使用例では、それらを符号なしlong(8桁の10の補数)または符号なし64ビット整数(16桁の10の補数または15桁と符号とフラグの余地)に格納します。それらを操作するために注意深く作られた算術ライブラリ。

実際には、もちろん、Cの実装では、標準で許可されているとおりに直接演算子をCPUのネイティブマシン命令にマッピングします。 この標準を書いた人々は、整数値の表現のような単純なものでさえも実装する多くの方法が存在することを非常に意識していました。機械。

代替案は、すべての数学演算が完全に指定されていて、どのマシンにも効率的に実装できない世界にすぐにつながります。


2


ISO C99は表現のどこかに符号ビットを必要としますが、さまざまな補数/符号と大きさスキームの間のオプションを与え、パディングビットを許可します。それらはすべて `>>`の操作に影響します。

_ _ セクション6.2.6.2(整数型)

符号付き整数型の場合、オブジェクト表現のビットは、値ビット、パディングビット、および符号ビットの3つのグループに分けられます。 パディングビットは必要ありません。符号ビットは1つだけです。 _ _

and

_ _ セクション6.5.7(ビット単位のシフト演算子)

E1 >> E2の結果は、E1の右シフトされたE2ビット位置です。 E1が符号なしタイプを持つ場合、またはE1が符号付きタイプと負でない値を持つ場合、結果の値はE1 / 2 ^ E2 ^の商の整数部です。 E1に符号付き型と負の値がある場合、結果の値は実装定義です。 _ _

これは、1の補数、2の補数、符号と大きさのどちらを使用するか、符号ビットが値ビットの左右どちらにあるか、またはパディングがあるところにあるかを指定しません。 > `符号付き否定の演算子です。

RBerteigの質問に答えて、C99は整数のBCD表現を排除します。

_ _ セクション6.2.6.2(整数型)

N個の値ビットがある場合、各ビットは1から2 N -1の間の異なる2のべき乗を表すものとし、そのためそのタイプのオブジェクトは純粋な2進表現を使用して0から2 N - 1までの値を表すことができる。これは値表現として知られるものとします。 _ _


0


C言語の実装では、ビットシフト操作を対応するマシンコード命令に直接マッピングする傾向があります。 ハードウェアアーキテクチャが異なれば歴史的に異なったことをしてきたので、C仕様はハードウェアが提供するものは何でも利用することができるようにC実装が定義されたものを定義したままにする傾向がある。


0


結果は実装に依存します。 しかし、実際には、私が今まで扱ったことのあるすべてのx86、PPC、およびMIPSコンパイラは、右に移動するためにこの規則に従いました。

  1. オペランドが符号付き整数の場合、空のビットは符号ビット(実際には最上位ビット)で埋められます。

  2. オペランドが符号なし整数の場合、空のビットはゼロで埋められます。

RBerteigが言っているように、これは正と負の両方のnに対して_signed_整数、n >> 1 = n / 2(丸め_down_)、そしてn> 2に対してさえn >> 1 = n / 2である31(32ビットアーキテクチャの場合)

対応するハードウェア命令は算術(符号拡張)および論理(符号拡張ではない)シフトです。オペランドが符号付きか符号なしかに基づいて、コンパイラはそれらを選択します。