Operatori di spostamento sinistro e destro: << e >>

Gli operatori di spostamento bit per bit sono l'operatore di spostamento a destra (>>), che sposta i bit di un'espressione di tipo integer o di enumerazione a destra e l'operatore di spostamento a sinistra (<<), che sposta i bit a sinistra. 1

Sintassi

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

Osservazioni:

Importante

Le descrizioni e gli esempi seguenti sono validi in Windows per architetture x86 e x64. L'implementazione degli operatori di spostamento a sinistra e a destra è significativamente diversa in Windows per i dispositivi ARM. Per altre informazioni, vedere la sezione "Shift Operators" del post di blog hello ARM .

Spostamenti a sinistra

L'operatore di spostamento a sinistra fa in modo che i bit in shift-expression vengano spostati a sinistra in base al numero di posizioni specificate da additive-expression. Le posizioni dei bit liberate dall'operazione di spostamento vengono riempite con zero. Uno spostamento a sinistra è uno spostamento logico (i bit spostati oltre la fine vengono eliminati, incluso il bit di segno). Per altre informazioni sui tipi di turni bit per bit, vedere Turni bit per bit.

Nell'esempio seguente vengono illustrate operazioni di spostamento a sinistra tramite numeri senza segno. Viene mostrato ciò che accade ai bit che rappresentano il valore come bitset. Per altre informazioni, vedere Classe 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
}

Se si sposta a sinistra un numero con segno coinvolgendo il bit di segno, il risultato sarà indefinito. L'esempio seguente mostra cosa accade quando un bit a 1 bit viene spostato a sinistra nella posizione del bit del segno.

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

Spostamenti a destra

L'operatore di spostamento a destra fa sì che il modello di bit in shift-expression venga spostato a destra in base al numero di posizioni specificate da additive-expression. Per i numeri senza segno, le posizioni dei bit liberate dall'operazione di spostamento vengono riempite con zero. Per i numeri con segno, il bit di segno viene utilizzato per riempire le posizioni dei bit liberate. In altre parole, se il numero è positivo, si utilizza 0, se il numero è negativo, si utilizza 1.

Importante

Il risultato di uno spostamento a destra di un numero negativo con segno è dipendente dall'implementazione. Anche se il compilatore Microsoft C++ usa il bit del segno per riempire le posizioni dei bit liberate, non c'è alcuna garanzia che anche altre implementazioni lo facciano.

Nell'esempio seguente vengono illustrate operazioni di spostamento a destra tramite numeri senza segno:

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

Nell'esempio seguente vengono illustrate operazioni di spostamento a destra tramite numeri con segno positivi.

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

Nell'esempio seguente vengono illustrate operazioni di spostamento a destra tramite numeri interi con segno negativi.

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

Turni e promozioni

Le espressioni su entrambi i lati di un operatore di spostamento devono essere tipi integrali. Le promozioni integrali vengono eseguite in base alle regole descritte in Conversioni standard. Il tipo del risultato è uguale al tipo dell'oggetto alzato shift-expressiondi livello.

Nell'esempio seguente una variabile di tipo viene alzata di livello char a .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
}

Dettagli

Il risultato di un'operazione di spostamento non è definito se additive-expression è negativo o se additive-expression è maggiore o uguale al numero di bit nell'oggetto (alzato di livello). shift-expression Non viene eseguita alcuna operazione di spostamento se 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)
}

Note a piè di pagina

1 Di seguito è riportata la descrizione degli operatori di spostamento nella specifica ISO C++11 (INCITS/ISO/IEC 14882-2011[2012]), sezioni 5.8.2 e 5.8.3.

Il valore di E1 << E2 è E1 spostato a sinistra di E2 posizioni di bit. I bit vuoti vengono riempiti con zero. Se E1 ha un tipo senza segno, il valore del risultato è E1 × 2E2, modulo ridotto uno più del valore massimo rappresentabile nel tipo di risultato. In caso contrario, se E1 ha un tipo firmato e un valore non negativo e E1 × 2E2 è rappresentabile nel tipo senza segno corrispondente del tipo di risultato, tale valore, convertito nel tipo di risultato, è il valore risultante; in caso contrario, il comportamento non è definito.

Il valore di E1 >> E2 è E1 spostato a destra di E2 posizioni di bit. Se E1 ha un tipo senza segno o se E1 ha un tipo con segno e un valore non negativo, il valore del risultato è la parte integrante del quoziente di E1/2E2. Se E1 dispone di un tipo signed e di un valore negativo, il valore risultante sarà definito dall'implementazione.

Vedi anche

Espressioni con operatori binari
Operatori, precedenza e associatività predefiniti C++