O que value & 0xff faz em Java?

98

Eu tenho o seguinte código Java:

byte value = 0xfe; // corresponds to -2 (signed) and 254 (unsigned)
int result = value & 0xff;

O resultado é 254 quando impresso, mas não tenho ideia de como esse código funciona. Se o &operador for simplesmente bit a bit, por que ele não resulta em um byte e, em vez disso, em um inteiro?

Dagronlund
fonte
Eu copio o código para o Eclipse. Avisa-me "Incompatibilidade de tipo: não é possível converter de inteiro em byte". Deve mudar para valor interno = 0xfe;
Ben Cheng
1
@BenCheng deveria serbyte value = (byte) 0xfe;
Bek

Respostas:

171

Ele define resulto valor (sem sinal) resultante de colocar os 8 bits de valuenos 8 bits mais baixos de result.

A razão pela qual algo assim é necessário é que byteé um tipo assinado em Java. Se você acabou de escrever:

int result = value;

então resultterminaria com o valor em ff ff ff fevez de 00 00 00 fe. Outra sutileza é que o &é definido para operar apenas nos intvalores 1 , então o que acontece é:

  1. valueé promovido a int( ff ff ff fe).
  2. 0xffé um intliteral ( 00 00 00 ff).
  3. O &é aplicado para produzir o valor desejado para result.

(A questão é que a conversão intocorre antes de o &operador ser aplicado.)

1 Bem, não exatamente. O &operador também trabalha com longvalores, se um dos operandos for um long. Mas não byte. Consulte a Especificação da linguagem Java, seções 15.22.1 e 5.6.2 .

Ted Hopp
fonte
O que ox significa nessa notação? x não é um número ou um número hexadecimal?
Callat
3
@KazRodgers - O prefixo 0x(ou 0X) diz ao Java que o literal inteiro que se segue deve ser interpretado como hex (base 16). Java também oferece suporte a um 0prefixo simples para literais octais e um prefixo 0b(ou 0B) para literais binários. Consulte a Especificação da linguagem Java para obter mais informações sobre literais inteiros.
Ted Hopp
O literal que se segue? Por exemplo, se eu tivesse 0x3fa. O 3fa é a parte sendo traduzida em um número literal e 0x indica "este é um número hexadecimal"? @TedHopp?
Callat
1
@KazRodgers - Exatamente. Observe que 0xou 0bpor si só (sem nenhum dígito após) é uma sintaxe ilegal em Java.
Ted Hopp
1
@DmitryMinkovsky - O padrão de bits hexadecimais feem 8 bits, o complemento de dois corresponde ao valor decimal -2. Para preservar o valor, Integer.valueOf(byte)seria necessário produzir ff ff ff fe(−2 em 32 bits, complemento de dois), não 00 00 00 fe(valor decimal 254). Essa transformação (de um bytevalor fepara um intvalor ff ff ff fe) é conhecida como extensão de sinal e faz parte da especificação da linguagem Java. O objetivo de value & 0xffé desfazer a extensão do sinal (ou seja, simular a extensão zero, algo que o Java não possui).
Ted Hopp
57

De http://www.coderanch.com/t/236675/java-programmer-SCJP/certification/xff

O literal hexadecimal 0xFF é um int igual (255). Java representa int como 32 bits. É parecido com isto em binário:

00000000 00000000 00000000 11111111

Quando você faz um AND bit a bit com este valor (255) em qualquer número, ele irá mascarar (fazer ZEROs) todos, exceto os 8 bits mais baixos do número (será como está).

... 01100100 00000101 & ...00000000 11111111 = 00000000 00000101

& é algo como%, mas não realmente .

E por que 0xff? isso em ((potência de 2) - 1). Todos ((potência de 2) - 1) (por exemplo, 7, 255 ...) se comportarão algo como% operador.

Então,
em binário, 0 é, todos zeros, e 255 se parece com isto:

00000000 00000000 00000000 11111111

E -1 é assim

11111111 11111111 11111111 11111111

Quando você faz um AND bit a bit de 0xFF e qualquer valor de 0 a 255, o resultado é exatamente o mesmo que o valor. E se qualquer valor superior a 255, o resultado ficará entre 0-255.

No entanto, se você:

-1 & 0xFF

você pega

00000000 00000000 00000000 11111111, que NÃO é igual ao valor original de -1 ( 11111111é 255 em decimal).


Pouca manipulação de bits a mais: (Não relacionado à questão)

X >> 1 = X/2
X << 1 = 2X

Verifique se qualquer bit em particular está definido (1) ou não (0), então

 int thirdBitTobeChecked =   1 << 2   (...0000100)
 int onWhichThisHasTobeTested = 5     (.......101)

 int isBitSet = onWhichThisHasTobeTested  & thirdBitTobeChecked;
 if(isBitSet > 0) {
  //Third Bit is set to 1 
 } 

Defina (1) um bit particular

 int thirdBitTobeSet =   1 << 2    (...0000100)
 int onWhichThisHasTobeSet = 2     (.......010)
 onWhichThisHasTobeSet |= thirdBitTobeSet;

ReSet (0) um bit particular

int thirdBitTobeReSet =   ~(1 << 2)  ; //(...1111011)
int onWhichThisHasTobeReSet = 6      ;//(.....000110)
onWhichThisHasTobeReSet &= thirdBitTobeReSet;

XOR

Observe que, se você executar a operação XOR duas vezes, o resultado será o mesmo valor.

byte toBeEncrypted = 0010 0110
byte salt          = 0100 1011

byte encryptedVal  =  toBeEncrypted ^ salt == 0110 1101
byte decryptedVal  =  encryptedVal  ^ salt == 0010 0110 == toBeEncrypted :)

Mais uma lógica com XOR é

if     A (XOR) B == C (salt)
then   C (XOR) B == A
       C (XOR) A == B

O acimaéútil para trocar duas variáveis ​​sem temp como abaixo

a = a ^ b; b = a ^ b; a = a ^ b;

OU

a ^= b ^= a ^= b;
Kanagavelu Sugumar
fonte
Também dê uma olhada em Manipulação de bits stackoverflow.com/questions/13422259/…
Kanagavelu Sugumar
4

Ajuda a reduzir muitos códigos. Ocasionalmente, é usado em valores RGB que consistem em 8 bits.

onde 0xff significa 24 (0's) e 8 (1's) como00000000 00000000 00000000 11111111

Ele efetivamente mascara a variável de modo que deixa apenas o valor nos últimos 8 bits e ignora todo o resto dos bits

É visto mais em casos como ao tentar transformar valores de cores de um formato especial para valores RGB padrão (que tem 8 bits).

Ótima Explicação Veja aqui

AndroidGeek
fonte
0

No sistema de formato de 32 bits, o valor hexadecimal 0xffrepresenta 00000000000000000000000011111111que está 255(15*16^1+15*16^0)em decimal. e o operador bit a bit & mascara os mesmos 8 bits mais à direita do primeiro operando.

Manish Kumar
fonte
Você pode explicar um pouco mais.
ashishdhiman2007