7

なぜ(-1 >> 1)結果になるの-1ですか?私はCで働いていますが、それは問題ではないと思います。

何が足りないのかわからない...

計算を行うCプログラムの例を次に示します。

#include <stdio.h>



int main()
{
    int num1 = -1;

    int num2 = (num1 >> 1);

    printf( "num1=%d", num1 );

    printf( "\nnum2=%d", num2 );

    return 0;
}
4

5 に答える 5

23

符号付き整数は2の補数表記で表されるためです。

-111111111(8ビットの数値の場合)になります。

-1 >> 1明らかに記号はそれが残るように拡張します11111111。この動作はコンパイラによって異なりますが、Microsoftの場合、符号付き数値を右にシフトすると(>>)、符号ビットがコピーされ、符号なし数値を右にシフトする0と、左端のビットにaが挿入されます。

于 2009-06-26T01:38:04.120 に答える
11

算術右シフトは、符号付き数値をシフトするときに符号を保持します。

11111111 (-1) will stay 11111111 (-1) 

対照的に、論理右シフトは符号を保持しません。

11111111 (-1) will become 01111111 (127)

コードは明らかに算術シフトを行うため、符号ビット(MSB)が繰り返されます。演算子(>>)が行うことは、使用しているプラ​​ットフォームの実装の詳細によって異なります。ほとんどの場合、それは算術シフトです。

11111111また、表現によっては2つの異なる意味を持つ可能性があることに注意してください。これは、シフトする方法にも影響します。

  • 符号なしの場合、11111111255を表します。MSBは符号ビットではないため、右にシフトしても符号は保持されません。
  • 署名されている場合、11111111-1を表します。算術的に右にシフトすると、記号が保持されます。
于 2009-06-26T01:42:02.100 に答える
5

負の数をビットシフトすることは、Cでの実装動作です。結果はプラットフォームによって異なり、理論的にはまったく無意味である可能性があります。C99標準(6.5.7.5)から:

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

これが発生する理由は、コンパイラがx86 SAR(Shift Arithmetic Right)命令を使用して>>を実装していることが原因である可能性があります。これは、符号拡張が発生することを意味します。値がシフトオーバーされると、最上位ビットが新しいMSBに複製されます。インテルのマニュアルから:

算術右シフト(SAR)および論理右シフト(SHR)命令は、デスティネーションオペランドのビットを右にシフトします(最下位ビット位置に向かって)。シフトカウントごとに、デスティネーションオペランドの最下位ビットがCFフラグにシフトされ、命令タイプに応じて最上位ビットがセットまたはクリアされます。SHR命令は、最上位ビットをクリアします(インテル®64およびIA-32アーキテクチャーソフトウェア開発者マニュアル、第1巻の図7-8を参照)。SAR命令は、デスティネーションオペランドの元の値の符号(最上位ビット)に対応する最上位ビットを設定またはクリアします。実際には、SAR命令は、空のビット位置のシフトされた値をシフトされていない値の符号で埋めます。(インテル®64およびIA-32アーキテクチャーソフトウェア開発者マニュアル第1巻の図7-9を参照)。

于 2009-06-26T01:36:40.940 に答える
3

右シフトして左端のビットが1の場合、一部のプラットフォーム/コンパイラは0を取り込み、一部は1を保持し、新しい左端のビットを1にします。これにより、数値の符号が保持されるため、負の数は負のままになります。符号拡張と呼ばれます。

を試してみると違いがわかります。((unsigned) -1) >> 1これは符号なしの右シフトを実行するため、常に0ビットでシフトします。

于 2009-06-26T01:38:30.360 に答える
1

符号拡張。

于 2009-06-26T01:35:45.997 に答える