Todo inteiro é guardado em binário. Operações bit a bit (bitwise) comparam ou movem esses bits um a um, sem passar pela aritmética comum.
Exemplo com a = 12 (1100) e b = 10 (1010):
| Operação | Go | Java | Regra | Resultado |
|---|---|---|---|---|
| AND | a & b | a & b | 1 se os dois bits são 1 | 1000 = 8 |
| OR | a | b | a | b | 1 se pelo menos um é 1 | 1110 = 14 |
| XOR | a ^ b | a ^ b | 1 se os bits são diferentes | 0110 = 6 |
| NOT | ^a | ~a | inverte todos os bits | -13 |
| AND NOT | a &^ b | a & ~b | limpa em a os bits ligados em b | 0100 = 4 |
| Desloca à esquerda | a << 1 | a << 1 | multiplica por 2 | 11000 = 24 |
| Desloca à direita | a >> 1 | a >> 1 | divide por 2 | 0110 = 6 |
Java ainda tem >>>, que desloca à direita preenchendo com zeros mesmo em números negativos. Em Go o mesmo efeito vem de usar tipos sem sinal (uint).
Onde aparece na prática
Flags e permissões: vários sim/não guardados em um único número. As permissões do Unix são isso: chmod 755 é 111 101 101 (dono lê, escreve, executa; grupo e outros leem e executam).
const ( Read = 1 << iota // 001 Write // 010 Exec // 100)
perm := Read | Write // liga leitura e escrita: 011canWrite := perm&Write != 0 // testa um bit: trueperm &^= Write // desliga a escrita: 001static final int READ = 1, WRITE = 1 << 1, EXEC = 1 << 2;
int perm = READ | WRITE;boolean canWrite = (perm & WRITE) != 0;perm &= ~WRITE;Truques rápidos: n & 1 diz se o número é ímpar; n & (n - 1) == 0 diz se é potência de 2 (para n > 0).
Máscaras: extrair parte de um valor, como o canal vermelho de uma cor 0xRRGGBB com (color >> 16) & 0xFF.
Veja também: Tipos de dados.