Operadores de desplazamiento a la izquierda y de desplazamiento a la derecha: << y >>

Los operadores de desplazamiento bit a bit son el operador de desplazamiento a la derecha (>>), que mueve los bits de una expresión de tipo entero o enumeración a la derecha y el operador de desplazamiento a la izquierda (<<), que mueve los bits a la izquierda. 1

Sintaxis

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

Observaciones

Importante

Las descripciones y ejemplos siguientes son válidas en Windows para arquitecturas x86 y x64. La implementación de operadores de desplazamiento izquierdo y de desplazamiento a la derecha es significativamente diferente en Windows para dispositivos ARM. Para obtener más información, consulte la sección "Operadores de desplazamiento" de la entrada de blog Hello ARM .

Desplazamientos a la izquierda

El operador de desplazamiento a la izquierda hace que los bits de shift-expression se cambien a la izquierda por el número de posiciones especificadas por additive-expression. Las posiciones de bits que la operación de desplazamiento ha anulado son de relleno cero. Un desplazamiento izquierdo es un desplazamiento lógico (los bits que se desplazan fuera del final se descartan, incluido el bit de signo). Para obtener más información sobre los tipos de desplazamientos bit a bit, vea Desplazamientos bit a bit.

En el ejemplo siguiente se muestran las operaciones de desplazamiento a la izquierda mediante números sin signo. En el ejemplo se muestra lo que sucede con los bits mediante la representación del valor como un conjunto de bits. Para obtener más información, vea Clase de conjunto de bits.

#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 desplaza un número con signo a la izquierda para que el bit de signo se vea afectado, el resultado no está definido. En el ejemplo siguiente se muestra lo que sucede cuando un bit de 1 bit se desplaza a la izquierda en la posición del bit de signo.

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

Desplazamientos a la derecha

El operador de desplazamiento a la derecha hace que el patrón de bits de shift-expression se desplaze a la derecha por el número de posiciones especificadas por additive-expression. En el caso de los números sin signo, las posiciones de bits que la operación de desplazamiento ha anulado son de relleno cero. En el caso de los números con signo, el bit de signo se usa para rellenar las posiciones de bits vacías. Es decir, si el número es positivo, se usa 0 y, si el número es negativo, se usa 1.

Importante

El resultado de un desplazamiento derecho de un número negativo firmado depende de la implementación. Aunque el compilador de Microsoft C++ usa el bit de signo para rellenar las posiciones de bits vacías, no hay ninguna garantía de que otras implementaciones también lo hagan.

En este ejemplo se muestran las operaciones de desplazamiento derecho mediante números sin signo:

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

En el ejemplo siguiente se muestran las operaciones de desplazamiento a la derecha con números con signo positivo.

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

En el ejemplo siguiente se muestran las operaciones de desplazamiento a la derecha con enteros con signo negativo.

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

Turnos y promociones

Las expresiones de ambos lados de un operador de desplazamiento deben ser tipos enteros. Las promociones integrales se realizan según las reglas descritas en Conversiones estándar. El tipo del resultado es el mismo que el tipo del promocionado shift-expression.

En el ejemplo siguiente, se promueve una variable de tipo 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
}

Detalles

El resultado de una operación de desplazamiento no está definido si additive-expression es negativo o si additive-expression es mayor o igual que el número de bits de (promocionado). shift-expression No se realiza ninguna operación de desplazamiento si additive-expression es 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)
}

Footnotes

1 La siguiente es la descripción de los operadores de desplazamiento en la especificación ISO de C++11 (INCITS/ISO/IEC 14882-2011[2012]), secciones 5.8.2 y 5.8.3.

El valor de es E1 posiciones de E1 << E2 bits desplazadas E2 a la izquierda; los bits vacíos se rellenan con cero. Si E1 tiene un tipo sin signo, el valor del resultado es E1 × 2E2, módulo reducido uno más que el valor máximo que se puede representar en el tipo de resultado. De lo contrario, si E1 tiene un tipo con signo y un valor no negativo, y E1 × 2E2 se puede representar en el tipo sin signo correspondiente del tipo de resultado, ese valor, convertido al tipo de resultado, es el valor resultante; de lo contrario, el comportamiento no está definido.

El valor de es E1 posiciones de E1 >> E2 bits desplazadas E2 a la derecha. Si E1 tiene un tipo sin signo o si E1 tiene un tipo con signo y un valor no negativo, el valor del resultado es la parte integral del cociente de E1/2E2. Si E1 tiene un tipo firmado y un valor negativo, el valor resultante es definido por la implementación.

Consulte también

Expresiones con operadores binarios
Operadores integrados de C++, precedencia y asociatividad