Links- und Rechtverschiebungsoperatoren: << und >>

Bei den bitweisen Verschiebungsoperatoren handelt es sich um den Rechtsverschiebungsoperator (>>), der die Bits eines Ganzzahl- oder Enumerationstypausdrucks nach rechts verschiebt, und den Linksverschiebungsoperator (<<), der die Bits nach links verschiebt. 1

Syntax

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

Hinweise

Wichtig

Die folgenden Beschreibungen und Beispiele gelten unter Windows für x86- und x64-Architekturen. Die Implementierung der Links- und Rechtsverschiebungsoperatoren unterscheidet sich bei Windows für ARM-Geräte deutlich. Weitere Informationen finden Sie im Abschnitt „Shift Operators“ des Blogbeitrags Hello ARM.

Verschiebungen nach links

Der Linksverschiebungsoperator bewirkt, dass die Bits in shift-expression um die Anzahl von Positionen nach links verschoben werden, die durch additive-expression angegeben wird. Die durch den Verschiebevorgang frei gewordenen Bitpositionen werden mit Nullen angefüllt. Eine Verschiebung nach links ist eine logische Verschiebung (die Bits, die über das Ende hinaus verschoben werden, werden verworfen, einschließlich des Vorzeichenbits). Weitere Informationen zu den Arten von bitweisen Verschiebungen finden Sie unter Bitweises Verschieben.

Im folgenden Codebeispiel wird veranschaulicht, wie Verschiebevorgänge nach links nicht signierte Zahlen verwenden. Das folgende Beispiel veranschaulicht, was mit den Bits geschieht, indem der Wert als ein Bitset dargestellt wird. Weitere Informationen finden Sie unter bitset-Klasse.

#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
}

Wenn Sie eine signierte Zahl nach links verschieben, sodass das Vorzeichenbit davon betroffen ist, ist das Ergebnis nicht definiert. Das folgende Beispiel veranschaulicht, was geschieht, wenn ein 1-Bit nach links in die Vorzeichenbitposition verschoben wird.

#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
}

Verschiebungen nach rechts

Der Rechtsverschiebungsoperator bewirkt, dass das Bitmuster in shift-expression um die Anzahl von Positionen nach rechts verschoben wird, die durch additive-expression angegeben wird. Für unsignierte Zahlen werden die durch den Verschiebevorgang frei gewordenen Bitpositionen mit Nullen angefüllt. Für signierte Zahlen wird das Vorzeichenbit verwendet, um die frei gewordenen Bitpositionen zu füllen. In anderen Worten, wenn die Zahl positiv ist, wird 0 verwendet, und wenn die Zahl negativ ist, wird 1 verwendet.

Wichtig

Das Ergebnis der Verschiebung einer signierten negativen Zahl nach rechts ist implementierungsabhängig. Obwohl der Microsoft C++-Compiler das Vorzeichenbit verwendet, um frei gewordene Bitpositionen zu füllen, gibt es keine Garantie, dass auch andere Implementierungen dies tun.

Dieses Beispiel veranschaulicht, wie Verschiebevorgänge nach rechts nicht signierte Zahlen verwenden:

#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
}

Das nächste Beispiel zeigt Verschiebevorgänge nach rechts mit positiven, signierten Zahlen.

#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
}

Das nächste Beispiel zeigt Verschiebevorgänge nach rechts mit negativen, signierten Ganzzahlen.

#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
}

Verschiebungen und Höherstufungen

Die Ausdrücke auf beiden Seiten eines Schiebeoperators müssen vom Typ „Ganzzahl“ sein. Integrale Höherstufungen werden gemäß den unter Standardkonvertierungen beschriebenen Regeln durchgeführt. Der Ergebnistyp entspricht dem Typ des höhergestuften Ausdrucks shift-expression.

Im folgenden Beispiel wird eine Variable vom Typ char zu einem int höhergestuft.

#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
}

Details

Das Ergebnis eines Verschiebevorgangs ist nicht definiert, wenn additive-expression negativ ist oder wenn additive-expression größer oder gleich der Anzahl von Bits im (höhergestuften) Ausdruck shift-expression ist. Wenn additive-expression gleich 0 ist, wird kein Verschiebevorgang durchgeführt.

#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)
}

Fußnoten

1 Es folgt die Beschreibung der Verschiebeoperatoren in der C++11 ISO-Spezifikation (INCITS/ISO/IEC 14882-2011[2012]), Abschnitte 5.8.2 und 5.8.3.

Der Wert von E1 << E2 ist E1 nach links verschobene E2-Bitpositionen; frei gewordene Bitpositionen werden mit Nullen angefüllt. Wenn E1 einen vorzeichenlosen Typ hat, lautet der Ergebniswert E1 × 2E2, wobei der Modulo eins mehr reduziert wird als der Maximalwert, der im Ergebnistyp dargestellt werden kann. Wenn andernfalls E1 einen Typ mit Vorzeichen und einen nicht negativen Wert hat und E1 × 2E2 im entsprechenden vorzeichenlosen Typ des Ergebnistyps dargestellt werden kann, ist dieser in den Ergebnistyp konvertierte Wert der Ergebniswert. Andernfalls ist das Verhalten nicht definiert.

Der Wert von E1 >> E2 ist E1 nach rechts verschobene E2-Bitpositionen. Wenn E1 einen vorzeichenlosen Typ hat oder E1 einen Typ mit Vorzeichen und einen nicht negativen Wert hat, dann ist der Ergebniswert der ganzzahlige Teil des Quotienten von E1/2E2. Wenn E1 einen signierten Typ und einen negativen Wert hat, ist der Ergebniswert durch die Implementierung definiert.

Siehe auch

Ausdrücke mit binären Operatoren
Integrierte C++-Operatoren, Rangfolge und Assoziativität