as mudanças de bits são por vezes consideradas operações bitwise, porque eles tratam um valor como uma série de bits ao invés de como uma quantidade numérica. Nestas operações os dígitos são movidos, ou deslocados, para a esquerda ou para a direita. Registradores em um processador de computador têm uma largura fixa, de modo que alguns bits serão “deslocados” do registrador em uma extremidade, enquanto o mesmo número de bits são “deslocados” da outra extremidade; as diferenças entre operadores de deslocamento de bits residem em como eles determinam os valores dos bits deslocados.
bit addressingEdit
If the width of the register (frequently 32 or even 64) is larger than the number of bits (usually 8) of the smallest addressable unit (atomic element), frequently called byte, the shift operations induz an addressing scheme on the bits.Desconsiderando os efeitos de contorno em ambas as extremidades do registrador, as operações aritméticas e de deslocamento lógico comportam-se da mesma forma, e um deslocamento de 8 bits de posições transporta o padrão de bits por 1 byte de forma a seguir:
|
uma esquerda shift por 8 posições aumenta o byte de endereço 1 |
|
um shift direita por 8 posições diminui o byte de endereço 1 |
|
uma esquerda shift por 8 posições diminui o byte de endereço 1 |
|
um shift direita por 8 posições aumenta o byte de endereço 1 |
Aritmética shiftEdit
Em uma aritmética deslocamento, os bits são deslocados para fora de cada extremidade são descartadas. Num turno aritmético à esquerda, os zeros são deslocados para a direita.; em uma mudança aritmética direita, o bit do sinal (o MSB no complemento de dois) é deslocado para a esquerda, preservando assim o sinal do operando.
Este exemplo usa um formato de 8 bits registrar, interpretado como complemento de dois:
00010111 (decimal +23) LEFT-SHIFT= 00101110 (decimal +46)
10010111 (decimal −105) RIGHT-SHIFT= 11001011 (decimal −53)
No primeiro caso, o dígito da esquerda foi deslocado passado fim do registro, e um novo 0 foi deslocado para a posição mais à direita. No segundo caso, o 1 mais à direita foi deslocado para fora (talvez para a bandeira carry), e um 1 Novo foi copiado para a posição mais à esquerda, preservando o sinal do número. Vários turnos são por vezes encurtados para um único turno por um número de dígitos. Por exemplo:
00010111 (decimal +23) LEFT-SHIFT-BY-TWO= 01011100 (decimal +92)
uma mudança aritmética da esquerda por n é equivalente à multiplicação por 2n (desde que o valor não transborde), enquanto uma mudança aritmética da direita por n do valor do complemento de dois é equivalente à divisão por 2n e arredondamento para o infinito negativo. Se o número binário é tratado como complemento de um, então a mesma operação de turno direito resulta em divisão por 2n e arredondamento para zero.
shiftEdit lógico
a Esquerda deslocamento lógico
|
Direito deslocamento lógico
|
Em uma lógica de mudança, zeros são deslocadas para substituir os rejeitados bits. Portanto, as mudanças lógicas e aritméticas à esquerda são exatamente as mesmas.
no entanto, como o deslocamento lógico para a direita insere o valor 0 bits no bit mais significativo, em vez de copiar o bit do sinal, é ideal para números binários sem sinal, enquanto o deslocamento aritmético para a direita é ideal para números binários de complemento de dois assinados.
outras informações: deslocamento Circular
outra forma de deslocamento é o deslocamento circular, rotação bidirecional ou rotação de bits.
RotateEdit
Deixado circular a tecla shift ou girar
|
Direito de circular shift ou girar
|
nesta operação, às vezes chamado de rodar sem transporte, os bits são “rodado”, como se as extremidades direita e esquerda do registrador foram associados. O valor que é deslocado para a direita durante um deslocamento para a esquerda é qualquer valor que foi deslocado para a esquerda, e vice-versa para uma operação de deslocamento para a direita. Isto é útil se for necessário reter todos os bits existentes, e é frequentemente usado em criptografia digital.
Girar através de carryEdit
a Esquerda girar através de transportar
|
Direito girar através de transportar
|
Girar através de carry é uma variante da operação de rotação, onde o bit que é deslocado (no final) é o antigo valor do flag de carry e o bit que é deslocado para fora (no outro extremo) se torna o novo valor do flag de carry.
uma única rotação através do carry pode simular uma mudança lógica ou aritmética de uma posição, configurando a bandeira de carry antes. Por exemplo, se a bandeira carry contém 0, então x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE
é um deslocamento lógico para a direita, e se a bandeira carry contém uma cópia do bit do sinal, então x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE
é um deslocamento aritmético para a direita. Por esta razão, alguns microcontroladores, como as fotos de ponta baixa, apenas têm rotação e rotação através de carry, e não se incomodam com instruções de deslocamento aritmético ou lógico.
rodar através do carry é especialmente útil quando realizar turnos em números maiores do que o tamanho nativo da palavra do processador, porque se um grande número é armazenado em dois registros, o bit que é deslocado de uma extremidade do primeiro registro deve entrar na outra extremidade do segundo. Com o road-through-carry, esse bit é “salvo” na bandeira carry durante o primeiro turno, pronto para mudar durante o segundo turno, sem qualquer preparação extra.
em línguas de alto nível
c-familyEdit
em línguas da família C, os operadores de mudança lógica são “<<
“para o turno da esquerda e” >>
” para o turno da direita. O número de lugares a mudar é dado como o segundo argumento para o operador. Por exemplo,
x = y << 2;
atribui x
o resultado de mudar y
para a esquerda por dois bits, que é equivalente a uma multiplicação por quatro.
mudanças podem resultar em um comportamento definido pela implementação ou um comportamento indefinido, por isso cuidado deve ser tomado ao usá-los. O resultado do deslocamento por uma contagem de bits maior ou igual ao tamanho da palavra é o comportamento indefinido em C e c++. A mudança para a direita um valor negativo é definido pela implementação e não recomendado pelas boas práticas de codificação; o resultado da mudança para a esquerda de um valor assinado é indefinido se o resultado não puder ser representado no tipo de resultado.
In C#, the right-shift is an arithmetic shift when the first operand is an int or long. Se o primeiro operando é do tipo uint ou ulong, o turno da direita é um deslocamento lógico.
shiftsEdit Circular
the C-family of languages lack a rotate operator, but one can be synthesized from the shift operators. Deve ter-se o cuidado de garantir que a declaração está bem formada para evitar ataques de comportamento indefinido e de timing em software com requisitos de segurança. Por exemplo, uma implementação ingênua que gira à esquerda um valor sem sinal de 32 bits x
por n
posições é simplesmente:
uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (32 - n));
no Entanto, uma mudança por 0
bits resulta em comportamento indefinido na mão direita expressão (x >> (32 - n))
porque 32 - 0
é 32
, e 32
está fora do intervalo inclusiva. Uma segunda tentativa pode resultar em:
uint32_t x = ..., n = ...;uint32_t y = n ? (x << n) | (x >> (32 - n)) : x;
onde a quantidade de deslocamento é testada para garantir que não introduz um comportamento indefinido. No entanto, o ramo adiciona um caminho de código adicional e apresenta uma oportunidade para análise de tempo e ataque, o que muitas vezes não é aceitável em software de alta integridade. Além disso, o código compila para várias instruções da máquina, que muitas vezes é menos eficiente do que a instrução nativa do processador.
para evitar o comportamento indefinido e ramos sob GCC e Clang, recomenda-se o seguinte. O padrão é reconhecido por muitos compiladores, e o compilador emitirá uma única rotação de instrução:
uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (-n & 31));
Há também compilador específico intrínsecos de execução circular turnos, como _rotl8, _rotl16, _rotr8, _rotr16 no Microsoft Visual C++. Clang fornece alguns rotativos intrinsics para a compatibilidade da Microsoft que sofre os problemas acima. O GCC não oferece rotações intrinsecamente. Intel também fornece x86 Intrinsics.
JavaEdit
In Java, all integer types are signed, so the” <<
“and” >>
” operators perform arithmetic shifts. Java adiciona o operador “>>>
” para realizar turnos lógicos à direita, mas como as operações de deslocamento lógico e aritmético à esquerda são idênticas para inteiro assinado, não há nenhum operador “<<<
” em Java.
mais detalhes dos operadores de shift Java:
- the operators
<<
(left shift),>>
(signed right shift), and>>>
(unsigned right shift) are called the shift operators. - o tipo de expressão de deslocamento é o tipo promovido do operando da esquerda. Por exemplo,
aByte >>> 2
é equivalente a((int) aByte) >>> 2
. - If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. É como se o operando-direito fosse submetido a um lógico e operador bitwise & com o valor da máscara 0x1f (0b11111). A distância de deslocamento realmente utilizada é, portanto, sempre na faixa de 0 a 31, inclusive.
- se o tipo promovido do operando da esquerda é longo, então apenas os seis bits de menor ordem do operando da direita são usados como a distância de deslocamento. É como se o operando-direito fosse submetido a um lógico e operador bidirecional & com o valor da máscara 0x3f (0b111111). A distância de deslocamento realmente utilizada é, portanto, sempre na faixa de 0 a 63, inclusive.
- o valor de
n > >> s
é N posições de bits com extensão zero. - em operações de bits e turnos, o tipo
byte
é implicitamente convertido paraint
. Se o valor de byte é negativo, o bit mais alto é um, então os são usados para preencher os bytes extras no int. Sobyte b1 = -5; int i = b1 / 0x0200;
resultarão emi = = -5
.
JavaScriptEdit
JavaScript usa operações bitwise para avaliar cada uma de duas ou mais unidades em 1 ou 0.
PascalEdit
In Pascal, as well as in all its dialects( such as Object Pascal and Standard Pascal), the logical left and right shift operators are “shl
” and ” shr
“, respectively. Mesmo para inteiros assinados, shr
comporta-se como uma mudança lógica, e não copia o bit do sinal. O número de lugares a mudar é dado como o segundo argumento. Por exemplo, o seguinte atribui x o resultado de mudar y para a esquerda por dois bits:
x := y shl 2;