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/

Share

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.