"Olá, amigo!"

"Também gostaria de falar sobre bitmasks e XOR."

"Você já sabe que os números consistem em bits e pode executar várias operações nesses bits. Uma máscara de bits é uma representação de vários valores lógicos diferentes (valores verdadeiro/falso) como um único inteiro. Nesse caso, cada valor booleano corresponde a um bit específico. Veja como isso pode ser feito:"

"A representação binária de potências de dois (1, 2, 4, 8, 16, 32, ...) envolve apenas a configuração de um bit:"

Número representação binária
1 0000 0001
2 0000 0010
4 0000 0100
8 0000 1000
16 0001 0000
19 (não uma potência de dois) 0001 0011
31 (não uma potência de dois) 0001 1111

"Portanto, qualquer número inteiro pode ser tratado como uma matriz de bits ou uma matriz de valores booleanos."

"Veja como você pode armazenar diferentes valores booleanos em um número:"

valores booleanos
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
Valores agrupados em um número:
int result = 0;
 if (a) result += 1; // 1 == 20 — bit 0
 if (b) result += 2; // 2 == 21 — bit 1
 if (c) result += 4; // 4 == 22 — bit 2
 if (d) result += 8; // 8 == 23 — bit 3

"Agora cada bit é 1 se a variável booleana correspondente for verdadeira."

No nosso caso, as variáveis ​​a e c eram verdadeiras, então o resultado é igual a 1+4 == 5

0000 0101
0000 dcba

"Acho que sei o que está acontecendo."

"Bem, se você entende, vamos seguir em frente."

"Um int tem 32 bits. Um deles é usado para o sinal do número, e os outros 31 podem ser usados ​​para armazenar os valores de 31 variáveis ​​booleanas."

"Um long tem 64 bits onde podemos armazenar 63 variáveis ​​booleanas."

"Sim."

"Dezenas de variáveis ​​amontoadas em um número. Isso é bastante."

"Mas onde isso é aplicado?"

"Principalmente em situações em que você precisa armazenar muitas informações sobre objetos. Quando você armazena muitas informações sobre um objeto, sempre há algumas dezenas de variáveis ​​booleanas. "Com essa abordagem, todas elas são convenientemente armazenadas em um número ."

"Com ênfase na palavra 'armazenado'. Porque realmente usar o número não é tão conveniente."

"A propósito, era exatamente isso que eu queria perguntar. Como extraímos o valor booleano do número?"

"Não é nada complicado. Digamos que você precise determinar se o bit 6 está definido como 1 (2 elevado a cinco é 32). Poderíamos verificar assim:"

Combine números em um:
int a = 32; // 25 == 0010 0000
int b = 8; // 23 == 0000 1000
int c = 2; // 21 == 0000 0010

int result = a + b + c; // 32 + 8 + 2 == 42 == 0010 1010
Extraia valores verificando bits específicos:
int a = result & 32; // 0010 1010 & 0010 0000 = 0010 0000
int b = result & 8; // 0010 1010 & 0000 1000 = 0000 1000
int c = result & 2; // 0010 1010 & 0000 0010 = 0000 0010

"Assim, trabalhar com bitmasks envolve três operações:"

1)  Definir um bit específico para 0

2)  Defina um bit específico para 1

3)  Verifique o valor do bit específico.

"Pegue o bit 6, por exemplo."

"Como você define o bit 6 para 1?"

Código Descrição
result = result | 01000000;
result |= 01000000;
Como você define o bit 6 para 1?
result = result & 10111111;
result &= 10111111;
Como você define o bit 6 como 0?
c = result & 01000000;
Como você obtém o valor do bit 6?

"Isso é muito incomum, mas não é difícil. Cara, agora eu sou um programador talentoso."

"E mais uma pequena dica sobre como obter facilmente números com um bit específico definido como 0 ou 1: 01000000 ou 10111111."

Para isso, temos os  operadores >> << .

"1 é 2 elevado a zero. Em outras palavras, um número com o bit 0 definido como 1. Precisamos de um número com o bit 6 definido."

int c = 1 << 6; // 0000 0001 << 6 == 0100 0000 == 64

"Legal! Isso é muito útil para esses casos."

"Mas e se eu precisar de um número em que cada bit seja definido como 1, exceto um bit específico definido como 0?"

"Isso também não é difícil:"

int d = ~(1 << 6); // ~0100 0000 == 10111111

"Em outras palavras, é tudo muito simples:"

Código Descrição
result = result | (1 << 6);
result |= (1 << 6);
Como você define o bit 6 para 1?
result = result & ~(1 << 6);
result &= ~(1 << 6);
Como você define o bit 6 como 0?
c = result & (1 << 6);
Como você obtém o valor do bit 6?

"Não parece muito difícil. Mas não vou me lembrar imediatamente."

"Mas, se você encontrar uma expressão assustadora como "resultado &= ~(1 << 6)" no código de outra pessoa, saberá que essa pessoa está apenas trabalhando com uma máscara de bits."

"E se você o encontrar com frequência, ele se lembrará de si mesmo para você."

"Lembre-se... Isso soa bem. Obrigado pela lição."