logotipo

27 de abril de 2024

Portas lógicas e operadores bitwise

Conceitos de computação

A lógica booleana é uma parte da álgebra abstrata que lida com operadores lógicos, conjuntos e com afirmações. Nela, tudo gira em torno de dois valores: 1 e 0, verdadeiro e falso, ligado e desligado, ou como você quiser chamar. Como nomeamos esses dois valores não é importante, mas por convenção, usamos o 0 para representar um valor nulo — ou desligado — e 1 para ligado. E você sabe o que é isso. É um bit. A lógica booleana gira em torno de bits. Muitos deles para criar uma lógica muito complexa. E, aliás, ela recebe esse nome como uma homenagem ao seu criador, George Boole.

No processador do computador, por exemplo, existem bilhões de componentes chamados transistores. Esses componentes permitem, com a potência computacional que temos hoje, realizar até bilhões de cálculos por segundo graças a lógica booleana. Os transistores são os blocos de construção básicos dos circuitos eletrônicos e são essenciais para a criação das portas lógicas.

Portas lógicas

Existem vários tipos de portas lógicas, mas o que elas fazem em comum é receber um ou mais valores e retornar outro como resultado. As mais importantes são NOT, NAND, NOR, AND e OR. Na imagem abaixo temos os valores A e B e seu retorno X para cada uma dessas portas.

Portas lógicas

NOT

Recebe um bit e retorna o seu valor invertido. 1 se torna 0 e 0 se torna 1. É como perguntar “Qual o inverso desse valor?”.

AND

Recebe dois ou mais valores de entrada e retorna verdadeiro se todos esses valores são verdadeiros. Portanto, é como perguntar: “Todos esses valores são válidos?”

OR

A porta OR (ou) retorna verdadeiro se pelo menos uma de suas entradas é verdadeira. “Alguma dessas entradas tem valor verdadeiro?”

NAND

É uma porta AND, porém com sua resposta invertida. Se no AND se perguntamos se todos os valores são verdadeiros, aqui proponho abstrairmos para: “Algum desses valores não é verdadeiro?”

NOR

É uma porta OR com seu resultado invertido. Basicamente, verifica se algum valor de entrada é falso. Se no OR é retornado verdadeiro para qualquer entrada positiva, nesse caso retornamos verdadeiro quando nenhuma das entradas forem verdadeiras. É como se perguntar: “Todos esses valores são falsos?” ou “Nenhuma dessas entradas são válidas?”

EXCLUSIVE OR

XOR representation

Essa outra porta não está na figura acima, porém vale a pena lembrá-la também. Permite verificar se as duas entradas têm valores diferentes uns dos outros. A abstração em forma de pergunta fica bem simples: “Essas entradas são diferentes?”

EXCLUSIVE NOR

XNOR representation

Aqui verificamos se as entradas são iguais, ou dois valores verdadeiros, ou dois valores falsos. Então, é como perguntar: “Essas entradas são iguais?”

Operações bitwise

Operações bitwise ou bit-a-bit são comparações e manipulações feitas entre bits, geralmente agrupados em 8 (um byte, portanto). São especialmente úteis em programação de baixo nível, criação de drivers, decodificação, sistemas embarcados e outros.

Ao fazer uma operação bit-a-bit nesse valor, cada bit é manipulado de cada vez. Em operações que recebem dois bytes, por exemplo, A e B, comparemos o primeiro bit do primeiro byte A com o primeiro bit do byte B, e assim por diante, até finalizar a manipulação.

Os operadores mais comuns são &, |, ^, ~, << e >>.

Operador & (AND)

Retornar 1 se ambos os bits são 1. Você pode combinar esse operador com zeros para limpar uma parte de um bit.

Operador | (OR)

Retorna 1 se algum dos bits em comparação é igual a 1.

Operador ^ (EXCLUSIVE OR)

Retorna true se os dois valores forem diferentes.

Podemos usar para inverter os valores de duas variáveis sem usar uma terceira variável, da seguinte forma:

1void inplace_swap(int *x, int *y) 2{ 3 *y = *x ^ *y; 4 *x = *x ^ *y; 5 *y = *x ^ *y; 6}


Operador ~ (NOT)

Pode inverter um byte inteiro. Por exemplo, a variável A é 0b00001010, então ~A é 0b11110101.

Operador << (Deslocamento à esquerda)

Desloca todos os bits para a esquerda. O bit que estava na ponta esquerda é deletado.

Esse operador pode servir para multiplicar números binários por 2. Por exemplo, 0b00000001 é 1 em decimal. Se usarmos 0b00000001 << 1, teremos o resultado 0b00000010, ou seja, 2 em decimal. 0b00000010 << 1 = 0b00000100 = 4, etc.

É possível movimentar mais de uma posição de cada vez: 0b00000001 << 2 = 0b00000100.

Operador >> (Deslocamento à direita)

Bem similar ao anterior, porém desloca todos os bits para a direita.

Exemplos

1#include <stdio.h> 2 3int main() { 4 int x = 5; // Representado como 0b00000101 em binário 5 int y = 3; // Representado como 0b00000011 em binário 6 7 // Operação de AND 8 int result_and = x & y; // 0b00000001 9 10 // Operação de OR 11 int result_or = x | y; // 0b00000111 12 13 // Operação de XOR 14 int result_xor = x ^ y; // 0b00000110 15 16 // Operação de NOT 17 int result_not_x = ~x; // 0b11111010 18 19 // Operação de deslocamento a esquerda 20 int result_left_shift = x << 1; // 0b00001010 21 22 // Operação de deslocamento a direita 23 int result_right_shift = y >> 1; // 0b00000001 24 25 printf("AND: %d\\n", result_and); 26 printf("OR: %d\\n", result_or); 27 printf("XOR: %d\\n", result_xor); 28 printf("NOT (x): %d\\n", result_not_x); 29 printf("Left Shift: %d\\n", result_left_shift); 30 printf("Right Shift: %d\\n", result_right_shift); 31 32 return 0; 33}

Em Resumo

As portas lógicas, como NOT, AND, OR, NAND, NOR, XOR e XNOR, fornecem a base para construir circuitos que realizam operações lógicas e tomam decisões com base em múltiplas entradas. Essas portas, combinadas em circuitos mais complexos, formam a base de todos os sistemas digitais.

Por outro lado, as operações bitwise permitem manipular dados binários ao nível granular, bit a bit. Essas operações são especialmente úteis em cenários onde a eficiência e o desempenho são críticos, como em programação de baixo nível, sistemas embarcados e operações de manipulação de dados.

Juntos, esses conceitos formam a base da computação moderna, permitindo que os computadores realizem cálculos complexos, tomem decisões e processem uma quantidade incrível de informações em uma fração de segundo.

Referências

Voltar para todos os artigos