O que significa "(int) value & 0x1, (int) value & 0x2, (int) value & 0x4, (int) value & 0x8" significa? "

11

código

O "valor" varia de 0 a 15 (seus valores possíveis). Quando essas 4 condições "se" serão atendidas? Se meu (int) valor = 2, isso significa 0010?

            if  ((int)value & 0x1) 
            {
                //statement here
            }
            if  ((int)value & 0x2) 
            {
                //statement here
            }
            if  ((int)value & 0x4) 
            {
                //statement here
            }
            if  ((int)value & 0x8) 
            {
                //statement here
            }
Sean McCarthy
fonte
3
Essas são máscaras de bits verificando bits individuais de value(leia-se if(value & 0x4)"É o terceiro bit do valueconjunto (= 1)). Como você aparentemente tem problemas para entender o código, presumo que ele não seja o seu. Isso (e o fato de você não estar perguntando para revisão) faz esta pergunta off-topic para CR.SE .
Ninguém
Para uma melhor compreensão, código semelhante que foi portado para C # usará o Enum.HasFlagmétodo para testar bits. Veja: Enum.HasFlag .
Rwong

Respostas:

12

Cada número pode ser expresso como value = b0*2^0 + b1*2^1 + b2*2^2 + b3*2^3 + ...cada b sendo um 0ou 1(estes são os bits da representação). Esta é a representação binária.

O AND binário ( &) leva cada um desses bpares de maneira sábia e executa E neles. Isso tem as seguintes saídas:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

Usando potências de 2 (que possuem apenas um único bit), podemos isolar e testar os bits individuais:

  • value & 1é verdadeiro quando valueé ímpar {1, 3, 5, 7, 9, 11, 13, 15}.

  • value & 2é verdadeiro quando value/2é ímpar {2, 3, 6, 7, 10, 11, 14, 15}.

  • value & 4é verdadeiro quando value/4é ímpar {4, 5, 6, 7, 12, 13, 14, 15}.

  • value & 8é verdadeiro quando value/8é ímpar {8, 9, 10, 11, 12, 13, 14, 15}.

O prefixo 0x nos números significa que ele deve ser interpretado como um número hexadecimal . É um pouco supérfluo quando você atinge apenas 0x8, mas informa aos mantenedores que provavelmente é usado como máscara de bit.

catraca arrepiante
fonte
1
A redação pode sugerir que ela pode ser estendida a todos os números, o que não é verdade: 8/6é ímpar, enquanto 8&6produz falso.
Sjoerd
@Sjoerd, é por isso que eu disse "poderes de 2"
catraca aberração
5

Essas instruções if verificam se um bit específico valueestá definido.

O valor hexadecimal 0x4, por exemplo, tem o terceiro bit da direita definido como 1e todos os outros bits definidos como 0. Quando você usa o binário- e o operador ( &) com dois operantes, o resultado terá todos os bits definidos, 0exceto os bits que são 1 nos dois operadores.

Portanto, quando você faz o cálculo value & 0x4, você fica binário 00000000ou binário 00000100, dependendo de o terceiro bit de valueser 1ou não 0. O primeiro avalia como false, e o segundo true, para que o bloco if seja executado apenas para valores em que o terceiro bit está definido.

Philipp
fonte
1

Há duas coisas interessantes a serem observadas aqui.

Primeiro, esse é um padrão comum para verificar cada um dos 4 bits de ordem inferior de um valor integral. A condição if é atendida se o bit correspondente estiver definido. Para o valor 2, o padrão de bits é de fato 0010.

A outra pergunta mais interessante é por que o (int)elenco? Além do estilo ruim de usar conversão C em C ++, nenhum valor inteiro ou caractere exige essa conversão. Um bool não faz sentido, um double / float seria convertido em um número inteiro temporário e seria incomum usar valores literais para testar uma enumeração. Pode fazer sentido com um ponteiro, mas isso seria um uso muito especializado. Conclusão: o elenco não faz sentido.

david.pfx
fonte