Opérateurs de décalage vers la gauche et vers la droite : << et >>

Les opérateurs de décalage au niveau du bit sont l’opérateur de décalage vers la droite (>>), qui déplace les bits d’une expression de type entier ou énumération vers la droite, et l’opérateur de décalage vers la gauche (<<), qui déplace les bits vers la gauche. 1

Syntaxe

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

Notes

Important

Les descriptions et les exemples suivants sont valides sur Windows pour les architectures x86 et x64. L’implémentation des opérateurs de décalage vers la gauche et vers la droite est très différente sur Windows pour les appareils ARM. Pour plus d’informations, consultez la section « Shift Operators » du billet de blog Hello ARM.

Décalages vers la gauche

L’opérateur de décalage vers la gauche entraîne le décalage des bits de shift-expression vers la gauche en fonction du nombre de positions spécifié par additive-expression. Les positions de bits qui ont été libérées par l'opération de décalage sont remplies de zéros. Un décalage vers la gauche est un décalage logique (les bits qui sont déplacés après la fin sont ignorés, y compris le bit de signe). Pour plus d’informations sur les différents genres de décalages au niveau du bit, consultez Décalages au niveau du bit.

L'exemple suivant illustre les opérations de décalage vers la gauche à l'aide de nombres non signés. L'exemple montre ce qui arrive aux bits en représentant la valeur en tant que bitset. Pour plus d’informations, consultez bitset, classe.

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

Si vous décalez vers la gauche un nombre signé de manière à affecter le bit de signe, le résultat n'est pas défini. L’exemple suivant montre ce qui se passe quand un bit 1 est décalé vers la gauche à la position du bit de signe.

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

Décalages vers la droite

L’opérateur de décalage vers la droite entraîne le décalage du modèle de bits de shift-expression vers la droite en fonction du nombre de positions spécifié par additive-expression. Pour les nombres non signés, les positions de bit qui ont été libérées par l'opération de décalage sont remplies de zéros. Pour les nombres signés, le bit de signe est utilisé pour remplir les positions de bit libérées. En d'autres termes, si le nombre est positif, 0 est utilisé, et si le nombre est négatif, 1 est utilisé.

Important

Le résultat d'un décalage vers la droite d'une nombre négatif signé dépend de l'implémentation. Bien que le compilateur Microsoft C++ utilise le bit de signe pour remplir les positions de bits vacantes, il n’existe aucune garantie que les autres implémentations le fassent également.

Cet exemple illustre les opérations de décalage vers la droite à l'aide de nombres non signés :

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

L'exemple suivant illustre les opérations de décalage vers la droite avec des nombres positifs signés.

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

L'exemple suivant illustre les opérations de décalage vers la droite avec des entiers négatifs signés.

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

Décalages et promotions

Les expressions des deux côtés de l'opérateur de décalage doivent être de type intégral. Les promotions de types intégraux sont effectuées en fonction des règles décrites dans Conversions standard. Le type du résultat est identique au type du shift-expression promu.

Dans l’exemple suivant, une variable de type char est promue en 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
}

Détails

Le résultat d’une opération de décalage est indéfini si additive-expression est négatif, ou si additive-expression est supérieur ou égal au nombre de bits dans le shift-expression (promu). Aucune opération de décalage n’a lieu si additive-expression a la valeur 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)
}

Notes de bas de page

1 Vous trouverez ci-dessous la description des opérateurs de décalage dans la spécification ISO C++11 (INCITS/ISO/IEC 14882-2011[2012]), sections 5.8.2 et 5.8.3.

La valeur de E1 << E2 est E1 décalée vers la gauche de positions de bit E2 ; les bits libérés sont remplis de zéros. Si E1 a un type non signé, le résultat est E1 × 2E2. Ce résultat est ensuite ajusté par l’opération de modulo avec la valeur maximale pouvant être représentée dans le type du résultat plus un. Sinon, si E1 a un type signé et une valeur non négative, et si E1 × 2E2 peut être représenté dans le type non signé correspondant du type du résultat, cette valeur, convertie vers le type du résultat, est la valeur résultante. Dans le cas contraire, le comportement est indéfini.

La valeur de E1 >> E2 est E1 décalée vers la droite de positions de bit E2. Si E1 a un type non signé, ou si E1 a un type signé et une valeur non négative, la valeur du résultat est la partie de type intégral du quotient de E1/2E2. Si E1 a un type signé et une valeur négative, la valeur résultante est définie par l'implémentation.

Voir aussi

Expressions avec des opérateurs binaires
Opérateurs intégrés, priorité et associativité C++