Udostępnij za pośrednictwem


Operatory przesunięcia w lewo i w prawo (>> i <<)

Operatory przesunięcia bitowego to operator przesunięcia w prawo (>>), który przesuwa bity shift_expression w prawo, i operator przesunięcia w lewo (<<), który przesuwa bity shift_expression w lewo.1

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

Uwagi

Ważna uwagaWażne

Następujące opisy i przykłady są prawidłowe w systemie Windows dla architektur x86 i x64.Implementacja operatorów przesunięcia w lewo i przesunięcia w prawo znacznie się różni w systemie Windows RT dla urządzeń ARM.Aby uzyskać więcej informacji, zobacz część "Shift operatorów" cześć ARM wpis w blogu.

Przesunięcia w lewo

Operator przesunięcia w lewo powoduje, że bity w shift-expression są przesuwane w lewo o liczbę pozycji określoną 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 rodzaju zmian bitowe, zobacz bitowe zmian.

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 — Klasa.

#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;  // 0000000000000100

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

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

Jeśli przesuniesz liczbę ze znakiem w lewo, tak że bit znaku zostanie objęty zmianą, wynik będzie nieokreślony.Poniższy przykład pokazuje, co się dzieje w Visual C++, 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{short2};
    cout << bitset1 << endl;  // 0100000000000000 

    short short3 = short1 << 1;
    bitset<16> bitset3{short3};  // 16384 left-shifted by 1 = -32768
    cout << bitset3 << endl;  // 100000000000000
 
    short short4 = short1 << 14;
    bitset<16> bitset4{short4};  // 4 left-shifted by 14 = 0
    cout << bitset4 << endl;  // 000000000000000  
}

Przesunięcia w prawo

Operator przesunięcia w prawo powoduje, że wzorzec bitowy shift-expression jest przesuwany w prawo o liczbę pozycji określoną 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żna uwagaWażne

Wynik przesunięcia w prawo liczby ujemnej ze znakiem zależy od implementacji.Mimo że Visual C++ używa bitu znaku do wypełnienia zwolnionych pozycji bitów, nie ma gwarancji, że inne implementacje działają tak samo.

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;     // 0000010000000000

    unsigned short short12 = short11 >> 1;  // 512
    bitset<16> bitset12{short12};
    cout << bitset12 << endl;      // 0000010000000000

    unsigned short short13 = short11 >> 10;  // 1
    bitset<16> bitset13{short13};
    cout << bitset13 << endl;      // 0000000000000001

    nsigned short short14 = short11 >> 11;  // 0
    bitset<16> bitset14{short14};
    cout << bitset14 << endl;     // 0000000000000000}
}

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;     // 0000010000000000

    short short2 = short1 >> 1;  // 512
    bitset<16> bitset2{short2};
    cout << bitset2 << endl;      // 0000010000000000

    short short3 = short1 >> 11;  // 0
    bitset<16> bitset3{short3};   
    cout << bitset3 << endl;     // 0000000000000000
}

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;  // 1111111111110000

    short neg2 = neg1 >> 1; // -8
    bitset<16> bn2{neg2};
    cout << bn2 << endl;  // 1111111111111000

    short neg3 = neg1 >> 2; // -4
    bitset<16> bn3{neg3};
    cout << bn3 << endl;  // 1111111111111100

    short neg4 = neg1 >> 4; // -1
    bitset<16> bn4{neg4};    
    cout << bn4 << endl;  // 1111111111111111

    short neg5 = neg1 >> 5; // -1 
    bitset<16> bn5{neg5};    
    cout << bn5 << endl;  // 1111111111111111
}

Przesunięcia i awansowania

Wyrażenia po obu stronach operatora przesunięcia muszą być typami całkowitoliczbowymi.Awansowania całkowitoliczbowe odbywają się zgodnie z zasadami opisanymi w Promocje typów całkowitych.Typ wyniku jest taki sam jak typ awansowanego shift-expression.

W poniższym przykładzie, zmienna typu char jest awansowana do 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
}

Dodatkowe szczegóły

Wynik operacji przesunięcia jest nieokreślony, jeżeli additive-expression jest ujemne lub jeżeli additive-expression jest większe niż lub równe liczbie bitów w (awansowanym) shift-expression.Operacja przesunięcia nie jest wykonywana, jeżeli 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;    // 00000000000000000000000000000100

    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;    // 00000000000000000000000000000100 (no change)}
}

Przypisy dolne

1 Poniżej znajduje się opis operatorów przesunięcia w specyfikacji C++ ISO (Stowarzyszenie INCITS/ISO/IEC 14882-2011[2012]), ppkt 5.8.2 i 5.8.3.

Wartość E1 << E2 to E1 przesunięte w lewo pozycje bitów E2; opuszczone bity są wypełnione przez zera.Jeśli E1 ma typ bez znaku, wartość wyniku jest E1 × 2E2, zmniejszone modulo o jeden więcej niż wartość maksymalna reprezentowana w typie wyniku.W przeciwnym razie, jeśli E1 ma typ ze znakiem i wartość nieujemną, i E1 × 2E2 jest reprezentowane w odpowiednim typie bez znaku typu wyniku, wówczas ta wartość, konwertowana na typ wyniku, jest wartością wynikową; w przeciwnym razie zachowanie jest nieokreślone.

Wartość E1 >> E2 to E1 przesunięte w prawo pozycje bitów E2.Jeśli E1 ma typ bez znaku lub jeśli E1 ma typ ze znakiem i wartość nieujemną, wartość wyniku jest integralną częścią ilorazu E1/2E2.Jeśli E1 ma typ ze znakiem i wartość ujemną, wartość wynikowa zależy od implementacji.

Zobacz też

Informacje

Wyrażenia z operatorami dwuargumentowymi

Operatory, pierwszeństwo i kojarzenie języka C++