左シフト演算子と右シフト演算子: <<>>

ビットごとのシフト演算子は右シフト演算子 (>>) であり、整数または列挙型の式のビットを右に移動し、左シフト演算子 (<<) を使用してビットを左に移動します。 1

構文

shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

注釈

Von Bedeutung

次の説明と例は、x86 および x64 アーキテクチャの Windows で有効です。 ARM デバイスの Windows では、左シフト演算子と右シフト演算子の実装が大きく異なります。 詳細については、 Hello ARM ブログ投稿の「Shift 演算子」セクションを参照してください。

左シフト

左シフト演算子を使用すると、 shift-expression 内のビットは、 additive-expressionで指定された位置の数だけ左にシフトされます。 シフト操作によって解放されたビット位置は、ゼロで埋められます。 左シフトは論理シフトです (末尾からシフトされたビットは、符号ビットを含めて破棄されます)。 ビットごとのシフトの種類の詳細については、「 ビットごとのシフト」を参照してください。

次の例は、符号なし数値を使用した左シフト操作を示しています。 この例では、値をビットセットとして表すことによってビットに何が起こっているかを示します。 詳細については、「 bitset クラス」を参照してください。

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    unsigned short short1 = 4;
    bitset<16> bitset1{short1};   // the bitset representation of 4
    cout << bitset1 << endl;  // 0b00000000'00000100

    unsigned short short2 = short1 << 1;     // 4 left-shifted by 1 = 8
    bitset<16> bitset2{short2};
    cout << bitset2 << endl;  // 0b00000000'00001000

    unsigned short short3 = short1 << 2;     // 4 left-shifted by 2 = 16
    bitset<16> bitset3{short3};
    cout << bitset3 << endl;  // 0b00000000'00010000
}

符号付き数値を左シフトして符号ビットが影響を受ける場合、結果は未定義になります。 次の例は、1 ビットが符号ビット位置に左シフトされた場合の動作を示しています。

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    short short1 = 16384;
    bitset<16> bitset1(short1);
    cout << bitset1 << endl;  // 0b01000000'00000000

    short short3 = short1 << 1;
    bitset<16> bitset3(short3);  // 16384 left-shifted by 1 = -32768
    cout << bitset3 << endl;  // 0b10000000'00000000

    short short4 = short1 << 14;
    bitset<16> bitset4(short4);  // 4 left-shifted by 14 = 0
    cout << bitset4 << endl;  // 0b00000000'00000000
}

右シフト

右シフト演算子を使用すると、 shift-expression のビット パターンは、 additive-expressionで指定された位置の数だけ右にシフトされます。 符号なし数値の場合、シフト操作によって空になったビット位置はゼロで埋められます。 符号付き数値の場合、符号ビットは空のビット位置を埋めるために使用されます。 つまり、数値が正の場合は 0 が使用され、数値が負の場合は 1 が使用されます。

Von Bedeutung

符号付き負数の右シフトの結果は、実装に依存します。 Microsoft C++ コンパイラでは、符号ビットを使用して空のビット位置を埋めますが、他の実装でもそうするという保証はありません。

この例では、符号なし数値を使用した右シフト操作を示します。

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    unsigned short short11 = 1024;
    bitset<16> bitset11{short11};
    cout << bitset11 << endl;     // 0b00000100'00000000

    unsigned short short12 = short11 >> 1;  // 512
    bitset<16> bitset12{short12};
    cout << bitset12 << endl;     // 0b00000010'00000000

    unsigned short short13 = short11 >> 10;  // 1
    bitset<16> bitset13{short13};
    cout << bitset13 << endl;     // 0b00000000'00000001

    unsigned short short14 = short11 >> 11;  // 0
    bitset<16> bitset14{short14};
    cout << bitset14 << endl;     // 0b00000000'00000000
}

次の例は、正の符号付き数値を持つ右シフト演算を示しています。

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    short short1 = 1024;
    bitset<16> bitset1(short1);
    cout << bitset1 << endl;     // 0b00000100'00000000

    short short2 = short1 >> 1;  // 512
    bitset<16> bitset2(short2);
    cout << bitset2 << endl;     // 0b00000010'00000000

    short short3 = short1 >> 11;  // 0
    bitset<16> bitset3(short3);
    cout << bitset3 << endl;     // 0b00000000'00000000
}

次の例は、負の符号付き整数を持つ右シフト演算を示しています。

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    short neg1 = -16;
    bitset<16> bn1(neg1);
    cout << bn1 << endl;  // 0b11111111'11110000

    short neg2 = neg1 >> 1; // -8
    bitset<16> bn2(neg2);
    cout << bn2 << endl;  // 0b11111111'11111000

    short neg3 = neg1 >> 2; // -4
    bitset<16> bn3(neg3);
    cout << bn3 << endl;  // 0b11111111'11111100

    short neg4 = neg1 >> 4; // -1
    bitset<16> bn4(neg4);
    cout << bn4 << endl;  // 0b11111111'11111111

    short neg5 = neg1 >> 5; // -1
    bitset<16> bn5(neg5);
    cout << bn5 << endl;  // 0b11111111'11111111
}

シフトとプロモーション

シフト演算子の両側の式は整数型である必要があります。 整数の昇格は、「 標準変換」で説明されている規則に従って実行されます。 結果の型は、昇格された shift-expressionの型と同じです。

次の例では、 char 型の変数が intに昇格されます。

#include <iostream>
#include <typeinfo>

using namespace std;

int main() {
    char char1 = 'a';

    auto promoted1 = char1 << 1;   // 194
    cout << typeid(promoted1).name() << endl;  // int

    auto promoted2 = char1 << 10;  // 99328
    cout << typeid(promoted2).name() << endl;  // int
}

詳細

シフト操作の結果は、 additive-expression が負の場合、または additive-expression が (昇格された) shift-expressionのビット数以上の場合は未定義です。 additive-expressionが 0 の場合、シフト操作は行われません。

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    unsigned int int1 = 4;
    bitset<32> b1{int1};
    cout << b1 << endl;    // 0b00000000'00000000'00000000'00000100

    unsigned int int2 = int1 << -3;  // C4293: '<<' : shift count negative or too big, undefined behavior
    unsigned int int3 = int1 >> -3;  // C4293: '>>' : shift count negative or too big, undefined behavior
    unsigned int int4 = int1 << 32;  // C4293: '<<' : shift count negative or too big, undefined behavior
    unsigned int int5 = int1 >> 32;  // C4293: '>>' : shift count negative or too big, undefined behavior
    unsigned int int6 = int1 << 0;
    bitset<32> b6{int6};
    cout << b6 << endl;    // 0b00000000'00000000'00000000'00000100 (no change)
}

脚注

1 C++11 ISO 仕様 (INCITS/ISO/IEC 14882-2011[2012])、セクション 5.8.2 および 5.8.3 のシフト演算子の説明を次に示します。

E1 << E2の値は、左シフトE2ビット位置E1。空のビットは 0 で塗りつぶされます。 E1に符号なし型がある場合、結果の値は E1 × 2E2 であり、結果の型で表される最大値より 1 つ小さい剰余が小さくなります。 それ以外の場合、 E1 に符号付き型と負以外の値があり、結果の型の対応する符号なし型で E1 × 2E2 が表される場合、その値は結果の型に変換され、結果の値になります。それ以外の場合、動作は未定義になります。

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

こちらも参照ください

二項演算子を含む式
C++ 組み込み演算子、優先順位、および結合規則