¿Qué hacen value & 0xff en Java?

98

Tengo el siguiente código Java:

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

El resultado es 254 cuando se imprime, pero no tengo idea de cómo funciona este código. Si el &operador es simplemente bit a bit, ¿por qué no da como resultado un byte y, en cambio, un entero?

dagronlund
fuente
Copio el código a Eclipse. Me advierte "No coinciden los tipos: no se puede convertir de int a byte". ¿Debería cambiar a int value = 0xfe;
Ben Cheng
1
@BenCheng debería serbyte value = (byte) 0xfe;
Bek

Respuestas:

171

Se establece resulten el valor (sin signo) resultante de colocar los 8 bits de valueen los 8 bits más bajos de result.

La razón por la que algo como esto es necesario es que bytees un tipo firmado en Java. Si acaba de escribir:

int result = value;

luego resultterminaría con el valor en ff ff ff felugar de 00 00 00 fe. Una sutileza adicional es que &está definido para operar solo en los intvalores 1 , por lo que lo que sucede es:

  1. valuese promueve a int( ff ff ff fe).
  2. 0xffes un intliteral ( 00 00 00 ff).
  3. Se &aplica para obtener el valor deseado result.

(El punto es que la conversión intocurre antes de& que se aplique el operador).

1 Bueno, no del todo. El &operador también trabaja con longvalores, si alguno de los operandos es un long. Pero no en byte. Consulte la Especificación del lenguaje Java, secciones 15.22.1 y 5.6.2 .

Ted Hopp
fuente
¿Qué significa la x en esa notación? ¿x no es un número o un número hexadecimal?
Llamado
3
@KazRodgers: el prefijo 0x(o 0X) le dice a Java que el literal entero que sigue debe interpretarse como hexadecimal (base 16). Java también admite un 0prefijo simple para literales octales y un prefijo 0b(o 0B) para literales binarios. Consulte la Especificación del lenguaje Java para obtener más información en literales enteros.
Ted Hopp
¿El literal que sigue? Entonces, por ejemplo, si tuviera 0x3fa. ¿El 3fa es la parte que se traduce a un número literal y 0x indica "este es un número hexadecimal"? @TedHopp?
Llamado el
1
@KazRodgers - Exactamente. Tenga en cuenta que 0xo 0bpor sí mismo (sin ningún dígito a continuación) es una sintaxis ilegal en Java.
Ted Hopp
1
@DmitryMinkovsky: el patrón de bits hexadecimales feen complemento a dos de 8 bits corresponde al valor decimal −2. Para conservar el valor, Integer.valueOf(byte)necesitaría producir ff ff ff fe(−2 en 32 bits, complemento a dos), no 00 00 00 fe(valor decimal 254). Esta transformación (de un bytevalor fea un intvalor ff ff ff fe) se conoce como extensión de signo y es parte de la especificación del lenguaje Java. El propósito de value & 0xffes deshacer la extensión del signo (es decir, simular la extensión cero, algo que Java no tiene).
Ted Hopp
57

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

El literal hexadecimal 0xFF es un int (255) igual. Java representa int como 32 bits. Se ve así en binario:

00000000 00000000 00000000 11111111

Cuando lo hace un poco Y con este valor (255) en cualquier número, va a enmascarar (hacer CERO) todos menos los 8 bits más bajos del número (será como está).

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

& es algo así como% pero no realmente .

¿Y por qué 0xff? esto en ((potencia de 2) - 1). Todos ((potencia de 2) - 1) (por ejemplo, 7, 255 ...) se comportarán de forma similar al operador%.

Luego,
en binario, 0 es, todo ceros y 255 se ve así:

00000000 00000000 00000000 11111111

Y -1 se ve así

11111111 11111111 11111111 11111111

Cuando hace un AND bit a bit de 0xFF y cualquier valor de 0 a 255, el resultado es exactamente el mismo que el valor. Y si todavía hay algún valor superior a 255, el resultado estará entre 0-255.

Sin embargo, si lo hace:

-1 & 0xFF

usted obtiene

00000000 00000000 00000000 11111111, que NO es igual al valor original de -1 ( 11111111es 255 en decimal).


Pocas manipulaciones de bits más: (No relacionado con la pregunta)

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

Verifique que cualquier bit en particular esté establecido (1) o no (0) luego

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

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

Establecer (1) un bit en particular

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

Restablecer (0) un bit en particular

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

XOR

Solo tenga en cuenta que si realiza la operación XOR dos veces, obtendrá el mismo valor.

byte toBeEncrypted = 0010 0110
byte salt          = 0100 1011

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

Una lógica más con XOR es

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

Lo anterior es útil para intercambiar dos variables sin temperatura como a continuación

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

O

a ^= b ^= a ^= b;
Kanagavelu Sugumar
fuente
También eche un vistazo a @ Bit manipulation stackoverflow.com/questions/13422259/…
Kanagavelu Sugumar
4

Ayuda a reducir muchos códigos. Ocasionalmente se utiliza en valores RGB que constan de 8 bits.

donde 0xff significa 24 (0's) y 8 (1's) como00000000 00000000 00000000 11111111

Enmascara efectivamente la variable, por lo que deja solo el valor en los últimos 8 bits e ignora el resto de los bits.

Se ve más en casos como cuando se intenta transformar valores de color de un formato especial a valores RGB estándar (que tiene una longitud de 8 bits).

Gran explicación ver aquí

AndroidGeek
fuente
0

En el sistema de formato de 32 bits, el valor hexadecimal 0xffrepresenta 00000000000000000000000011111111que está 255(15*16^1+15*16^0)en decimal. y el operador & bit a bit enmascara los mismos 8 bits más a la derecha que en el primer operando.

manish kumar
fuente
¿Puedes explicar un poco más?
ashishdhiman2007