Operadores de deslocamento à esquerda e deslocamento à direita: <<
e >>
Os operadores shift bit a bit são o operador shift para a direita (>>
), que move os bits de uma expressão de tipo de enumeração ou inteiro para a direita, e o operador shift para a esquerda (<<
), que move os bits para a esquerda. 1
Sintaxe
shift-expression
:
additive-expression
shift-expression
<<
additive-expression
shift-expression
>>
additive-expression
Comentários
Importante
As descrições e exemplos a seguir são válidos no Windows para arquiteturas x86 e x64. A implementação de operadores shift para a esquerda e direita é significativamente diferente no Windows para dispositivos ARM. Para obter mais informações, confira a seção sobre “operadores shift” do post do blog Hello ARM.
Deslocamentos para a esquerda
O operador shift para a esquerda faz com que os bits na shift-expression
sejam deslocados para a esquerda pelo número de posições especificadas pela additive-expression
. As posições de bits que foram liberadas pela operação de deslocamento são preenchidas com zeros. Um deslocamento para a esquerda é um deslocamento lógico (os bits que são deslocados da extremidade são descartados, incluindo o bit de sinal). Para obter mais informações sobre os tipos de operadores shift bit a bit, confira o artigo Bitwise shifts.
O exemplo a seguir mostra operações de deslocamento para a esquerda usando números sem sinal. O exemplo a seguir mostra o que está acontecendo com os bit representando o valor como um conjunto de bits. Para mais informações, confira Classe 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
}
Se você deslocar um número com sinal para a esquerda de forma que o bit de sinal seja afetado, o resultado será indefinido. O exemplo a seguir mostra o que acontece quando 1 bit é deslocado para a esquerda na posição de bit de sinal.
#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
}
Deslocamentos para a direita
O operador shift para a direita faz com que o padrão de bits na shift-expression
seja deslocado para a direita pelo número de posições especificadas pela additive-expression
. Para números sem sinal, as posições de bits que foram liberadas pela operação de deslocamento são preenchidas com zeros. Para números com sinal, o bit de sinal é usado para preencher as posições de bit vagas. Ou seja, se o número for positivo, 0 será usado, e se o número for negativo, 1 será usado.
Importante
O resultado do deslocamento de um número negativo para a direita dependerá da implementação. Embora o compilador Microsoft C++ use o bit de sinal para preencher as posições de bits vagas, não há garantia de que outras implementações também façam isso.
Este exemplo mostra operações de deslocamento para a direita usando números sem sinal:
#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
}
O próximo exemplo mostra operações de deslocamento para a direita com números positivos com sinal.
#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
}
O próximo exemplo mostra operações de deslocamento para a direita com inteiros negativos com sinal.
#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
}
Deslocamentos e promoções
As expressões em ambos os lados do operador shift devem ser tipos integrais. As promoções integrais são executadas de acordo com as regras descritas em Conversões padrão. O tipo do resultado é o mesmo tipo da shift-expression
promovida.
No exemplo a seguir, uma variável de tipo char
é promovida 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
}
Detalhes
O resultado de uma operação de deslocamento é indefinido quando a additive-expression
é negativa, ou se a additive-expression
for maior ou igual ao número de bits da shift-expression
(promovida). Nenhuma operação de deslocamento ocorre se additive-expression
é 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 de rodapé
1 Esta é a descrição dos operadores shift da especificação C++11 ISO (INCITS/ISO/IEC 14882-2011[2012]), seções 5.8.2 e 5.8.3.
O valor de E1 << E2
é E1
deslocado para a esquerda nas posições do bit E2
; os bits vagos são preenchidos por zero. Se E1
tiver um tipo sem sinal, o valor do resultado será E1 × 2E2, módulo reduzido uma vez mais que o valor máximo representável no tipo de resultado. Caso contrário, se E1
tiver um tipo com sinal e um valor não negativo, e E1 × 2E2 for representável no tipo sem sinal correspondente do tipo de resultado, esse valor, convertido no tipo de resultado, será o valor resultante; caso contrário, o comportamento será indefinido.
O valor de E1 >> E2
é E1
é deslocado para a direita nas posições do bit E2
. Se E1
tiver um tipo sem sinal ou se E1
tiver um tipo com sinal e um valor não negativo, o valor do resultado será a parte integral do quociente de E1/2E2. Se E1
tiver um tipo com sinal e um valor negativo, o valor resultante será definido pela implementação.
Confira também
Expressões com operadores binários
Operadores internos, precedência e associatividade no C++
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de