Pular para o conteúdo

Operações de bits

E, OU, OU exclusivo, NÃO com largura, deslocamento e contagem — como funções, e por que não operadores.

Máscara, flag, permissão em octal, cor num inteiro, soma de conferência: tudo isso é conta bit a bit. As funções moram em Arcane.Estrutura, com nomes que dizem o que fazem:

FunçãoFazNo C
bits_e(a, b)1 só onde os dois têm 1 — a máscaraa & b
bits_ou(a, b)liga o que estiver ligado em qualquer uma | b
bits_xou(a, b)1 onde diferem; aplicado duas vezes, desfaza ^ b
bits_nao(a, largura)inverte dentro da largura~a (com o tipo dando a largura)
deslocar(a, n)esquerda com n positivo, direita com negativoa << n / a >> -n
contar_uns(a)quantos bits ligados__builtin_popcount
bit_ligado(a, i) · ligar_bit · desligar_bitum bit só, contando de 0 embaixomáscara na mão
dataforge
adopt Arcane.Estrutura as Est

// permissões do Unix: rwx para o dono, r-x para o grupo, r-- para os outros
steady LER := 4
steady ESCREVER := 2
steady EXECUTAR := 1
dono := Est.bits_ou(Est.bits_ou(LER, ESCREVER), EXECUTAR)
modo := Est.bits_ou(Est.bits_ou(Est.deslocar(dono, 6), Est.deslocar(5, 3)), 4)
assert modo is 0o754

grupo := Est.bits_e(Est.deslocar(modo, -3), 7)
assert grupo is 5
assert not Est.bit_ligado(grupo, 1)                // o grupo não escreve

assert Est.bits_nao(0b10110000, 8) is 0b01001111    // dentro de um byte
assert Est.contar_uns(0xFF) is 8
assert Est.bits_xou(Est.bits_xou(1234, 0xABCD), 0xABCD) is 1234

Por que não operadores#

Os três símbolos que toda linguagem usa já têm dono aqui: >> é o pipeline, | é a união de tipos e & a interseção. Um a >> 2 que deslocasse bits mudaria o sentido de todo pipeline já escrito, e a & b numa anotação seria lido como tipo. Funções com nome não disputam nada — e deslocar(x, -4) diz o sentido, que é a dúvida de sempre com >>.

Para campos com nome dentro de um inteiro — versão e tamanho no mesmo byte —, Campos de bits é mais legível que máscara na mão.