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-expression
di 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
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++