Operadores bitwise [C/C++]
Programadores C/C++ conhecem diversos operadores da linguagem, embora alguns se mantenham desconhecidos de diversos. A tabela abaixo mostra os operadores da linguagem C/C++ e sua divisão em operadores unários, binários e ternários.
Dos operadores binários, alguns realizam operações em bits (os bitwises) são os menos conhecidos. Segue uma breve descrição de cada um deles:
- & (bitwise AND): compara os bits de dois valores binários e retorna 1 para cada par de bits iguais a 1, ou seja, o valor é 1 somente se ambos os bits for 1.
- | (bitwise OR): compara os bits de dois valores binários e retorna 1 se algum dos bits for igual a 1, ou seja, o valor é 1 se algum dos bits for 1.
- ^ (bitwise XOR): compara os bits de dois valores binários e retorna 1 se os dois bits são diferentes.
- ~ (bitwise NOT): Inverte todos os bits de um número. Considerando valores decimais, ele incrementa o valor em uma unidade e inverte o sinal.
- << (left shift – deslocamento de bits para a esquerda): desloca os bits para a esquerda o número de bits indicado. Cada deslocamento equivale a multiplicar por 2, ou seja, valor << 3, é o mesmo que multiplicar valor por 2 três vezes (ou seja, multiplicar por 6).
- >> (right shift – deslocamento de bits para a direita): desloca os bits para a direita o número de bits indicado. Cada deslocamento equivale a dividir o valor por 2, ou seja, valor >> 3, é o mesmo que dividir valor por 2 três vezes. Não chega ser o mesmo que dividir um valor por 6, uma vez que cada passo equivale ao resultado da divisão considerando apenas a parte inteira da divisão. Por exemplo, 36/6 = 6, enquanto 36>>3 = 4 => 100100>>1= 10010>>1= 1001>>1= 100 = 4 decimal.
A seguir é mostrado o resultado dos operadores bitwise AND, OR e XOR aplicados a dois valores. Em cada tabela estão os valores em sua representação binária na coluna da direita e na última linha o resultado da operação.
O resultado do operador NOT é mostrado abaixo, cujo dígitos 1 se tornam 0 e vice-versa.
Por fim, é mostrado abaixo a aplicação dos operadores >> e <<. Observe que o valor de 5>>1 é o mesmo que fazer 5/2. Como tanto o numerador quanto denominador são números inteiros, somente a parte inteira é resultante, ou seja, 5/2=2.
O código abaixo aplica os operadores bitwise para mostrar suas diferenças. Para isso são mostrados os valores decimais e seus correspondentes binários. A função print_binary() é a responsável por mostrar o valor binário e considera apenas os 4 primeiros bits (os 4 bits mais a direita). Veja que essa função, além de mostrar os valores em binários, sua construção utiliza os operadores bitwise fazendo um left shift e right shift, e o uso do bitwise AND. A função também foi construída utilizando um operador ternário, mostrando vários dos operadores da linguagem (são poucas linhas de código, mas que exigem um bom conhecimento para conseguir entender).
#include <stdio.h>
//representa uma valor decimal em binário com 4 bits
void print_binary(unsigned n) {
unsigned i;
for (i = 1 << 3; i > 0; i = i >> 1)
(n & i) ? printf("1") : printf("0");
}
int main() {
unsigned short a = 5; // 0101
unsigned short b = 1; // 0001
printf("a = %d, b = %d\n", a, b);
print_binary(a);
printf(" e ");
print_binary(b);
printf("\n a&b = %d - ", a & b);
print_binary(a&b); // 0001
printf("\n a|b = %d - ", a | b);
print_binary(a|b); // 0101
printf("\n a^b = %d - ", a ^ b);
print_binary(a^b); // 0100
printf("\n ~a = %d - ", ~a);
print_binary(~a); // 1010
printf("\n ~b = %d - ", ~b);
print_binary(~b); // 1010
printf("\n a<<1 = %d - ", a << 1);
print_binary(a << 1); // 10 e 1010
printf("\n a>>1 = %d - ", a >> 1);
print_binary(a>>1); // 2 e 0010
printf("\n b<<2 = %d - ", b << 2);
print_binary(b<<2); // 4 e 0100
printf("\n b>>2 = %d - ", b >> 2);
print_binary(b>>2); // 0 e 0000
}
Teste o código em: https://ideone.com/6HnADE
Vale dizer que é interessante conhecer os operadores bitwise para tirar proveito e inclusive otimizar o código. Veja um comparativo de desempenho do uso do operador de multiplicação com o left shift: http://www.galirows.com.br/meublog/competir/dicas/otimizacoes-para-o-codigo/utilize-operadores-bitwise/