¿Qué hace Y 0xFF?


En el siguiente código:

short = ((byte2 << 8) | (byte1 & 0xFF))

¿Cuál es el propósito de &0xFF? Porque otras veces lo veo escrito como:

short = ((byte2 << 8) | byte1)

Y eso parece funcionar bien también?

Author: Muis, 2013-02-05

7 answers

Y un entero con 0xFF deja solo el byte menos significativo. Por ejemplo, para obtener el primer byte en un short s, puede escribir s & 0xFF. Esto se conoce típicamente como"enmascaramiento". Si byte1 es un solo tipo de byte (como uint8_t) o ya es menor que 256 (y como resultado son todos los ceros excepto el byte menos significativo) no hay necesidad de enmascarar los bits más altos, ya que ya son cero.

Ver tristopia La respuesta de Patrick Schlüter a continuación cuando puede estar trabajando con tipos firmados. Al realizar operaciones bitwise, recomiendo trabajar solo con tipos sin signo.

 29
Author: John Colanduoni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-07 09:30:50

Si byte1 es un tipo entero de 8 bits, entonces no tiene sentido: si es más de 8 bits, esencialmente le dará los últimos 8 bits del valor:

    0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
 &  0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
    -------------------------------
    0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1
 22
Author: D Stanley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-05 17:18:59

El peligro de la segunda expresión viene si el tipo de byte1 es char. En ese caso, algunas implementaciones pueden tenerlo signed char, lo que resultará en una extensión de signo al evaluar.

signed char byte1 = 0x80;
signed char byte2 = 0x10;

unsigned short value1 = ((byte2 << 8) | (byte1 & 0xFF));
unsigned short value2 = ((byte2 << 8) | byte1);

printf("value1=%hu %hx\n", value1, value1);
printf("value2=%hu %hx\n", value2, value2);

Se imprimirá

value1=4224 1080     right
value2=65408 ff80    wrong!!

Lo probé en gcc v3.4.6 en Solaris SPARC 64 bit y el resultado es el mismo con byte1 y byte2 declarado como char.

TL; DR

El enmascaramiento es para evitar la extensión de signo implícita.

EDIT : He comprobado, es el mismo comportamiento en C++.

 19
Author: Patrick Schlüter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-06 07:37:07

Asumiendo que su byte1 es un byte(8bits), Cuando se hace un bit a bit Y de un byte con 0xFF, se obtiene el mismo byte.

Así que byte1 es lo mismo que byte1 & 0xFF

Decir byte1 es 01001101 , entonces byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1

Si el byte 1 es de algún otro tipo, digamos un entero de 4 bytes, a bit Y con 0xFF te deja con el byte menos significativo(8 bits) del byte 1.

 6
Author: Sibi Rajasekaran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-05 17:25:07

El byte1 & 0xff asegura que solo los 8 bits menos significativos de byte1 pueden ser distintos de cero.

Si byte1 ya es un tipo sin signo que tiene solo 8 bits (por ejemplo, char en algunos casos, o unsigned char en la mayoría) no hará ninguna diferencia/es completamente innecesario.

Si byte1 es un tipo que está firmado o tiene más de 8 bits (p. ej., short, int, long), y cualquiera de los bits excepto el 8 menos significativo se establece, entonces habrá una diferencia (es decir, cero los bits superiores antes oring con la otra variable, por lo que este operando de la or afecta solo los 8 bits menos significativos del resultado).

 3
Author: Jerry Coffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-05 18:01:13

Borra todos los bits que no están en el primer byte

 1
Author: thumbmunkeys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-05 17:17:20

& 0xFF por sí solo asegura que si los bytes son más largos que 8 bits (permitidos por el estándar de lenguaje), el resto se ignoran.

Y eso parece funcionar bien también?

Si el resultado termina siendo mayor que SHRT_MAX, se obtiene un comportamiento indefinido. En ese sentido, ambos funcionarán igualmente mal.

 0
Author: Alexey Frunze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-05 17:29:54