7

符号付きおよび符号なしの型に対するビット演算子の動作を理解しようとしています。ISO/IEC 文書によると、以下は私の理解です。

左シフト演算子

  • の結果はE1 << E2、E1 左シフトされた E2 ビット位置です。

  • 左シフトのために空になったビットはゼロで埋められます。

  • E1 as signed non-negative: E1 << E2値が結果の型で表現できる場合、E1 に E2 の 2 乗を掛けた結果になります。

  • Q1: 符号付きネガはどうですか?

  • Q2: 以下の文脈で「被減モジュロ」が何を意味するのか理解できません。「E1 が unsigned 型の場合、結果の値は E1 × 2E2 であり、結果の型で表現可能な最大値より 1 を法として減じられます」 .

右シフト演算子

  • の結果は、E1 >> E2E1 の右シフトされた E2 ビット位置です。

  • E1 as signed non-negative/unsigned : 結果の値は、E1 / 2E2 の商の整数部分です。

  • Q3: 符号付きの負の整数について、空いている位置が で埋められると定義している本をいくつか見ました。符号付きの負の整数1での右シフト演算子の使用について詳しく教えてください。

4

4 に答える 4

8

Q1: 符号付き整数型の負の値に対する左シフト演算子の動作は定義されていません。結果E1 * 2^E2が型で表現できない場合の符号付き整数型の正の値の動作も同様です。

これは、標準 (n1570 ドラフト) のセクション 6.5.7、パラグラフ 4 および 5 で明示的に言及されています。

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

Q2: 符号なし整数型で表現可能な最大値よりも 1 多いリダクション モジュロは、左にシフト アウトされたビットが単純に破棄されることを意味します。

数学的には、unsigned 型の最大値が2^n - 1(そして常にその形式である) 場合、ビット単位でE1左にシフトした結果は、0 から差がE2V2^n - 1

(E1 * 2^E2 - V)

で割り切れ2^nます。つまり、 で割った余りE1 * 2^E2です2^n

Q3: 符号付き整数型の負の値を右にシフトする際の動作は実装定義です。最も一般的な動作 (少なくとも 2 の補数マシンでは) は算術シフトです。つまり、結果は (負の無限大に向かって) 切り捨てられた商になります。

5 の結果E1 >> E2E1右シフトされたE2ビット位置です。E1が unsigned 型の場合、またはsignedE1型で非負の値の場合、結果の値は の商の整数部分ですE1 / 2^E2符号付きの型と負の値を持つ場合E1、結果の値は実装定義です。

于 2012-11-24T19:11:08.513 に答える
5
  • Re: Q1
    E1 が負の場合、動作は未定義です。

  • Re: Q2
    符号なし演算は「巡回」です。つまり、循環しUINT_MAX + 1ます0。あたかもすべての計算がモジュロ UINT_MAX+1 で行われたかのようです。別の考え方として、左に収まらない余分なビットは単純に削除されます。

  • Re: Q3
    E1 が負の場合、結果は実装定義です。つまり、マシン/コンパイラ/オプションに依存しますが、動作はどこかに文書化 (「定義」) する必要があります (通常はコンパイラのマニュアル)。2 つの一般的な選択肢は、左側の着信ビットを 1 (算術シフト) または 0 (論理シフト) で埋めることです。

于 2012-11-24T19:10:37.000 に答える
2

ビット単位のシフト演算子を本当に理解したい場合。次の簡単なルールを見てください。

1) 左シフト、E1 << E2 では、右側のすべての空きビットがゼロで埋められます。数値が符号付きか符号なしかに関係なく、常にゼロがシフトインされます。

2) 左シフトでは、E1 >> E2、左側のすべての空きビットは、数値が正の場合は 0 になり、数値が負の場合は 1 になります。符号なし数値は決して負ではないことに注意してください。また、一部の実装では、数値が負の場合でも一部のマシンでそれらを 0 で埋める可能性があるため、これに依存しないでください。

他のすべてのシナリオは、これら 2 つの単純なルールで説明できます。シフト後の結果の値を知りたい場合は、数字とシフトのビット表現を紙に手動で書き、これら2つのルールを使用して空きスペースにビットを入力します。そうすれば、ビットシフトがどのように機能するかをよりよく理解できるようになります。

For example lets take int i = 7;
i<<2
now i = 0000 0000 0000 0000 0000 0000 0000 0111
perform two left shits according to rule 1 would be:

0000 0000 0000 0000 0000 0000 0001 1100

これは 28 の値 ( E1 * 2E2 = 7 *2*2 = 28) を与えます。これは、ビット パターンで表されるものと同じです。

ここで、「縮小モジュロ」のことを説明します。大きな数値をシフトしている場合、左側のビットが失われるよりも、「縮小モジュロ」がそれを補います。したがって、結果の値が最大値より大きい場合データ型が保持できることを確認すると、左側のビットが失われ、結果 = (E1*2*E2) % ( maximumValue + 1) になります。

他のさまざまなケースでは、上記のルールを念頭に置いてください。

于 2012-11-24T19:28:44.767 に答える
1

Q2: 「value Reduced modulo X」は、数学では「value mod X」を意味し、C では「value % X」と書くことができます。その部分は、整数オーバーフローのしくみを説明しているだけです。

于 2012-11-24T19:10:48.007 に答える