La relación entre la función de & 0xFF y la conversión de tipos byte e Int

Cada vez que me encuentro con operaciones como AND o desplazamiento, siempre me confundo una vez. Baidu lo entiende y luego lo olvida. La comprensión no es lo suficientemente profunda y clara, y rara vez escribo sobre ello en el trabajo, así que lo escribo.

Accidentalmente revisé el código y encontré un fragmento de código que era difícil de entender.

byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ;  
        for (int i = 0; i < bs.length; i++) {
    
      
            int c = bs[i] & 0xFF ;
            if(c < 16){
    
     
                sb.append("0");  
            }  
            sb.append(Integer.toHexString(c)) ;  
        }  
        return sb.toString() ;

bs es una salida de matriz de bytes después del cifrado MD5 de una cadena. Al principio me resultó difícil entender por qué bs[i]&oxFF debería copiarse al tipo int en el siguiente ciclo.

bs[i] es un binario de 8 bits. Cuando 0xFF se convierte en un binario de 8 bits, es 11111111. Entonces, ¿bs[i]&0xFF no sigue siendo el mismo bs[i]? ¿Es esto interesante?

Más tarde escribí otra demostración.

package jvmProject;

public class Test {
    
    

    public static void main(String[] args) {
    
    
        byte[] a = new byte[10];
        a[0]= -127;
        System.out.println(a[0]);
        int c = a[0]&0xff;
        System.out.println(c);
    }
}

Primero imprimo un [0] y luego imprimo el valor después de un [0] y 0xff. Originalmente pensé que el resultado debería ser -127.

¡Pero el resultado es realmente inesperado!

-127

129

¿Por qué? &0xff está mal.

El cartel original realmente no lo entendía, por lo que pensó en ello más tarde para complementar el código.

Recuerdo que cuando estaba aprendiendo los principios de la informática, aprendí que el almacenamiento en la computadora se almacena mediante complemento binario.

Repasemos los tres conceptos de código original y código complementario.

Para el código original de un número positivo (00000001), el primer bit representa el bit de signo y el complemento del complemento es él mismo.
Para el código original de un número negativo (100000001), el complemento es la operación de inversión del original. código excepto el bit de signo, es decir (111111110), el código complementario es realizar una operación +1 en el código complementario, es decir, (111111111)
El concepto es tan simple como eso.

Cuando se asigna -127 a un [0], un [0] es un tipo de byte y su complemento almacenado en la computadora es 10000001 (8 bits).

Cuando un [0] se envía a la consola como un tipo int, JVM realiza un proceso de llenado de bits. Debido a que el tipo int es de 32 bits, el complemento después del llenado de bits es 11111111111111111111111111 10000001 (32 bits). Este complemento binario de 32 bits El código también representa -127.

No se encontró, aunque el código de complemento a dos almacenado detrás de la computadora byte->int se convirtió de 10000001 (8 bits) a 1111111111111111111111111 10000001 (32 bits). Obviamente, los números decimales representados por estos dos códigos de complemento siguen siendo los mismos.

¿Pero estoy haciendo una conversión byte->int solo para mantener la coherencia decimal?

¿Tal vez no? Por ejemplo, si el archivo que obtenemos se convierte en una matriz de bytes, ¿nos importa el valor decimal de la matriz de bytes? Lo que nos importa es el complemento del almacenamiento binario detrás de él, ¿verdad?

Por lo tanto, debería poder adivinar por qué el número de tipo de byte es &0xff y luego asignarlo al tipo int. La razón esencial es mantener la coherencia del complemento a dos.

Cuando el byte se convierte a int, los 24 bits altos inevitablemente se complementarán con 1. De esta manera, el complemento a dos es en realidad inconsistente. &0xff puede establecer los 24 bits altos en 0 y mantener los 8 bits bajos como están. El propósito de esto es garantizar la coherencia de los datos binarios.

Por supuesto, al tiempo que se garantiza la integridad de los datos binarios, si el binario se interpreta como byte e int, su valor decimal debe ser diferente porque la posición del bit de signo ha cambiado.

En el ejemplo 2, int c = a[0]&0xff; a[0]&0xff=1111111111111111111111111 10000001&11111111=0000000000000000000000000 10000001, este valor es 129.

Entonces el valor de salida de c es 129. Alguien preguntó por qué un [0] en la fórmula anterior no es de 8 bits sino de 32 bits. Esto se debe a que cuando el sistema detecta que un byte puede convertirse en int o realiza operaciones en los tipos byte e int, cambiará el bit alto del byte. espacio de memoria Agregue 1 (es decir, complete el bit de signo) a 32 bits y luego participe en la operación. El 0xff anterior es en realidad un valor literal de tipo int, por lo que se puede decir que se operan byte e int.

Supongo que te gusta

Origin blog.csdn.net/zch981964/article/details/132792875
Recomendado
Clasificación