157

C では、シフト演算子 ( <<>>) は算術演算ですか、それとも論理演算ですか?

4

11 に答える 11

162

左にシフトする場合、算術シフトと論理シフトに違いはありません。右にシフトする場合、シフトのタイプは、シフトされる値のタイプによって異なります。

(違いに不慣れな読者のための背景として、1 ビットの「論理的」右シフトは、すべてのビットを右にシフトし、左端のビットを 0 で埋めます。「算術」シフトは、元の値を左端のビットに残します。 . 負の数を扱う場合、違いが重要になります。)

符号なしの値をシフトする場合、C の >> 演算子は論理シフトです。符号付きの値をシフトする場合、>> 演算子は算術シフトです。

たとえば、32 ビット マシンを想定すると、次のようになります。

signed int x1 = 5;
assert((x1 >> 1) == 2);
signed int x2 = -5;
assert((x2 >> 1) == -3);
unsigned int x3 = (unsigned int)-5;
assert((x3 >> 1) == 0x7FFFFFFD);
于 2008-08-11T09:16:34.607 に答える
109

K&R 第 2 版によると、符号付き値の右シフトの結果は実装に依存します。

ウィキペディアによると、C/C++ は「通常」、符号付きの値に算術シフトを実装します。

基本的に、コンパイラをテストするか、コンパイラに依存しないようにする必要があります。現在の MS C++ コンパイラに関する私の VS2008 ヘルプには、コンパイラが算術シフトを行うと書かれています。

于 2008-08-11T09:18:29.533 に答える
18

あなたが得るシフトのタイプに関して、重要なことはあなたがシフトしている値のタイプです。バグの典型的な原因は、リテラルをシフトして、たとえばビットをマスクオフする場合です。たとえば、符号なし整数の左端のビットを削除したい場合は、これをマスクとして試してみてください。

~0 >> 1

残念ながら、シフトされる値(〜0)が符号付きであるため、マスクのすべてのビットが設定されるため、これは問題になります。したがって、算術シフトが実行されます。代わりに、値を符号なしとして明示的に宣言することによって、つまり次のようにすることによって、論理シフトを強制する必要があります。

~0U >> 1;
于 2008-08-13T17:20:06.173 に答える
17

C で int の論理右シフトと算術右シフトを保証する関数を次に示します。

int logicalRightShift(int x, int n) {
    return (unsigned)x >> n;
}
int arithmeticRightShift(int x, int n) {
    if (x < 0 && n > 0)
        return x >> n | ~(~0U >> n);
    else
        return x >> n;
}
于 2010-03-17T16:13:08.063 に答える
7

あなたがするとき - 1で左にシフトすると2で乗算されます - 1で右にシフトすると2で除算されます

 x = 5
 x >> 1
 x = 2 ( x=5/2)

 x = 5
 x << 1
 x = 10 (x=5*2)
于 2012-09-06T06:09:47.267 に答える
4

ウィキペディアで調べたところ、次のように書かれていました。

ただし、C には右シフト演算子 >> が 1 つしかありません。多くの C コンパイラは、シフトされる整数の型に応じて、実行する右シフトを選択します。多くの場合、符号付き整数は算術シフトを使用してシフトされ、符号なし整数は論理シフトを使用してシフトされます。

したがって、コンパイラに依存しているようです。また、その記事では、左シフトは算術と論理で同じであることに注意してください。境界ケース (もちろん上位ビット セット) でいくつかの符号付きおよび符号なしの数値を使用して簡単なテストを行い、コンパイラでの結果を確認することをお勧めします。また、C には標準がないように思われるため、少なくともそのような依存を回避することが合理的で可能である場合は、どちらか一方に依存することを避けることをお勧めします。

于 2008-08-11T09:18:52.247 に答える
0

は通常、符号なし変数の論理シフトと符号付き変数の左シフトに使用します。算術右シフトは、変数を符号拡張するため、本当に重要です。

は、他のコンパイラが使用する可能性が高いように、該当する場合にこれを使用します。

于 2008-08-14T00:15:02.687 に答える