lunes 3 de marzo de 2008

Java y los unsigned

La semana pasada tuve una batalla con Java: tenía que hacer una práctica trabajando con bits.

El nivel más bajo al cual se puede trabajar en Java con bits es el byte (8 bits). Un carácter hexadecimal son 4 bits, con lo cual nos caben 2 en un byte.

El problema viene cuándo, por ejemplo, quieres hacer una operación de unsigned bytes y asignarla a un int. Prueba de ello:

byte b = (byte) 0x01; //si no se pone "(byte)" da error al compilar porque se piensa que 0x01 es un int.
byte c = (byte) 0x80;
int a = 0; //(opcional) fuerzo a que todos los bits de 'a' sean 0
a = b | c;

El contenido de 'a' (visto en hexadecimal) es 0xffffff81, y pasado a decimal son -127.

Al final, la solución: unas máscaras...

byte b = (byte) 0x01;
byte c = (byte) 0x80;
int a = (b & 0xff) | (c & 0xff);

Ahora, el contenido de 'a' es 0x81 (0x00000081), que pasado a decimal son 129.

Por lo que puedo deducir, en 'c', al estar el bit más significativo a 1, y Java interpretarlo como un número negativo (signed), al convertirlo a int para poder hacer la operación, extiende el 1 hasta el final, que es lo que se ve al hacer la or binaria. Con las máscaras lo que hacemos es poner a 0 todos esos bits que Java extiende y que realmente no nos interesan debido a que queremos trabajar con unsigneds.

¿Alguna cosa más a tener en cuenta cuando se trabaja con bits en Java?