Operadores de desplazamiento izquierdo 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 de enumeración a la derecha, y el operador de desplazamiento izquierdo (<<
), que mueve los bits a la izquierda. 1
Sintaxis
shift-expression
:
additive-expression
shift-expression
<<
additive-expression
shift-expression
>>
additive-expression
Comentarios
Importante
Las descripciones y los ejemplos siguientes son válidos en Windows para las arquitecturas x86 y x64. La implementación de los operadores de desplazamiento a la izquierda y desplazamiento a la derecha es muy diferente en los dispositivos Windows para ARM. Para obtener más información, vea la sección sobre los operadores de desplazamiento en 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 desplacen hacia la izquierda el número de posiciones especificado por additive-expression
. Las posiciones de bits que quedan vacantes debido a la operación de desplazamiento se rellenan con ceros. Un desplazamiento a la izquierda es un desplazamiento lógico (los bits que se desplazan más allá del final se descartan, incluido el bit de signo). Para obtener más información sobre los tipos de desplazamiento bit a bit, vea el artículos sobre los desplazamientos bit a bit.
En el ejemplo siguiente se muestran operaciones de desplazamiento a la izquierda con números sin signo. El ejemplo muestra lo que ocurre con los bits representando el valor como un bitset. Para obtener más información, consulte Clase 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
}
Si desplaza a la izquierda un número con signo de modo que el bit de signo se vea afectado, el resultado es indefinido. En el ejemplo siguiente se muestra lo que ocurre cuando un 1 bit se desplaza a la izquierda hasta 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 desplace hacia la derecha el número de posiciones especificado por additive-expression
. En el caso de números sin signo, las posiciones de bits que quedan vacantes debido a la operación de desplazamiento se rellenan con ceros. Si se trata de números con signo, el bit de signo se emplea para rellenar las posiciones de bits vacantes. 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 a la derecha de un número negativo con signo depende de la implementación. Aunque el compilador de Microsoft C++ usa el bit de signo para rellenar las posiciones de bits vacantes, no hay ninguna garantía de que otras implementaciones también lo hagan.
En este ejemplo se muestran operaciones de desplazamiento a la derecha que usan 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 operaciones de desplazamiento a la derecha con números positivos con signo.
#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 operaciones de desplazamiento a la derecha con enteros negativos con signo.
#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
}
Desplazamientos y promociones
Las expresiones especificadas a ambos lados de un operador de desplazamiento deben ser de tipos enteros. Las promociones de enteros se realizan según las reglas que se describen en Conversiones estándar. El tipo del resultado es el mismo que el tipo de shift-expression
que se ha promovido.
En el ejemplo siguiente, una variable de tipo char
se promueve 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 es indefinido si additive-expression
es negativo o si additive-expression
es mayor o igual que el número de bits de shift-expression
(que se ha promovido). 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)
}
Notas al pie
1 A continuación se muestra 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 E1 << E2
es E1
desplazado a la izquierda E2
posiciones de bits; los bits vacantes se rellenan con ceros. Si E1
tiene un tipo sin signo, el valor resultante es E1 × 2E2, reduciendo cada módulo en uno más que el valor máximo que se puede representar en el tipo del 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 del resultado, ese valor, convertido al tipo del resultado, es el valor resultante; de lo contrario, el comportamiento es indefinido.
El valor de E1 >> E2
es E1
desplazado a la derecha E2
posiciones de bits. 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 entera del cociente de E1/2E2. Si E1
tiene un tipo con signo y un valor negativo, el valor resultante está definido por la implementación.
Consulte también
Expresiones con operadores binarios
Operadores integrados de C++, precedencia y asociatividad
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de