Operatory przesunięcia w lewo i w prawo: <<
i >>
Operatory przesunięcia bitowego to operator przesunięcia w prawo (>>
), który przenosi bity wyrażenia typu liczby całkowitej lub wyliczenia z prawej strony, a operator przesunięcia w lewo (<<
), który przenosi bity w lewo. 1
Składnia
shift-expression
:
additive-expression
shift-expression
<<
additive-expression
shift-expression
>>
additive-expression
Uwagi
Ważne
Poniższe opisy i przykłady są prawidłowe w systemie Windows dla architektur x86 i x64. Implementacja operatorów przesunięcia w lewo i w prawo jest znacznie inna w systemie Windows dla urządzeń z usługą ARM. Aby uzyskać więcej informacji, zobacz sekcję "Operatory shift" wpisu w blogu Hello ARM .
Przesunięcia w lewo
Operator przesunięcia w lewo powoduje przesunięcie bitów shift-expression
w lewo przez liczbę pozycji określonych przez additive-expression
. Pozycje bitów, które zostały zwolnione w wyniku operacji przesunięcia, są wypełniane przez zera. Przesunięcie w lewo to przesunięcie logiczne (bity, które zostaną przesunięte poza koniec, są odrzucane, łącznie z bitem znaku). Aby uzyskać więcej informacji na temat rodzajów przesunięć bitowych, zobacz Bitwise shifts (Przesunięcia bitowe).
W poniższym przykładzie pokazano operacje przesunięcia w lewo przy użyciu liczb bez znaku. W przykładzie pokazano, co się dzieje z bitami, poprzez reprezentowanie wartości jako zestawu bitów. Aby uzyskać więcej informacji, zobacz bitset Class (Klasa 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
}
Jeśli przesuniesz liczbę ze znakiem w lewo, tak że bit znaku zostanie objęty zmianą, wynik będzie nieokreślony. W poniższym przykładzie pokazano, co się stanie, gdy 1 bit jest przesunięty w lewo do pozycji bitu znaku.
#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
}
Przesunięcia w prawo
Operator przesunięcia po prawej stronie powoduje przesunięcie wzorca shift-expression
bitowego w prawo przez liczbę pozycji określonych przez additive-expression
. W przypadku liczb bez znaku, pozycje bitów, które zostały zwolnione w wyniku operacji przesunięcia, są wypełniane przez zera. W przypadku liczb ze znakiem, bit znaku jest używany do wypełniania opuszczonych pozycji bitów. Innymi słowy, jeśli liczba jest dodatnia, używane jest 0, a jeśli liczba jest ujemna, używane jest 1.
Ważne
Wynik przesunięcia w prawo liczby ujemnej ze znakiem zależy od implementacji. Mimo że kompilator języka Microsoft C++ używa bitu znaku do wypełnienia wolnych pozycji bitów, nie ma gwarancji, że inne implementacje również to robią.
W tym przykładzie pokazano operacje przesunięcia w prawo przy użyciu liczb bez znaku:
#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
}
W kolejnym przykładzie pokazano operacje przesunięcia w prawo przy użyciu liczb dodatnich ze znakiem.
#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
}
W następnym przykładzie pokazano operacje przesunięcia w prawo przy użyciu ujemnych liczb całkowitych ze znakiem.
#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
}
Zmiany i promocje
Wyrażenia po obu stronach operatora przesunięcia muszą być typami całkowitoliczbowymi. Promocje całkowite są wykonywane zgodnie z zasadami opisanymi w sekcji Konwersje standardowe. Typ wyniku jest taki sam jak typ promowanego shift-expression
elementu .
W poniższym przykładzie zmienna typu char
jest promowana do klasy 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
}
Szczegóły
Wynik operacji przesunięcia jest niezdefiniowany, jeśli additive-expression
jest ujemny lub jeśli additive-expression
jest większy lub równy liczbie bitów w (promowanym) shift-expression
. Operacja przesunięcia nie jest wykonywana, jeśli additive-expression
ma wartość 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)
}
Przypisy dolne
1 Poniżej przedstawiono opis operatorów przesunięcia w specyfikacji ISO języka C++11 (INCITS/ISO/IEC 14882-2011[2012]), sekcjach 5.8.2 i 5.8.3.
Wartość to E1
pozycje bitów E1 << E2
przesunięte E2
w lewo; puste bity są wypełnione zero. Jeśli E1
ma niepodpisany typ, wartość wyniku to E1 × 2E2, zmniejszona modulo o jedną więcej niż maksymalna wartość reprezentowana w typie wyniku. W przeciwnym razie, jeśli E1
ma typ ze znakiem i wartość nieujemną, a E1 × 2E2 jest reprezentowany w odpowiadającym niepodpisanym typie wyniku, to ta wartość, przekonwertowana na typ wyniku, jest wartością wynikową; w przeciwnym razie zachowanie jest niezdefiniowane.
Wartość to E1
pozycje E1 >> E2
bitów przesunięte E2
w prawo. Jeśli E1
typ niepodpisany lub jeśli E1
ma typ ze znakiem i wartość nieujemną, wartość wyniku jest integralną częścią ilorazu E1/2 E2. Jeśli E1
ma typ ze znakiem i wartość ujemną, wynikowa wartość jest zdefiniowana przez implementację.
Zobacz też
Wyrażenia z operatorami binarnymi
Wbudowane operatory, pierwszeństwo i kojarzenie języka C++
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla