variable son rotacion qué operadores manipulacion manejo los lenguaje ejemplos desplazamiento corrimiento complemento binaria c++ c bit-manipulation integer-promotion

c++ - son - rotacion de bits en c



¿Qué hay de malo con este código de manipulación de bits de una pregunta de entrevista? (7)

Creo que, dependiendo del tamaño de un largo, el literal 0xffff (-1) podría promoverse a un tamaño mayor y, al ser un valor con signo, se ampliará al signo, convirtiéndose potencialmente en 0xffffffff (aún -1).

Estaba revisando esta página: http://www.devbistro.com/tech-interview-questions/Cplusplus.jsp , y no entendí esta pregunta:

¿Qué es potencialmente malo con el siguiente código?

long value; //some stuff value &= 0xFFFF;

Nota: sugerir al candidato sobre la plataforma base para la que están desarrollando. Si la persona aún no encuentra ningún problema con el código, no tiene experiencia con C ++.

¿Alguien puede elaborar sobre esto?

¡Gracias!


El tipo de letra largo es específico de la plataforma / compilador.

Lo que puedes decir aquí es:

  1. Esta firmado
  2. No podemos saber el resultado del valor & = 0xFFFF; ya que podría ser, por ejemplo, un valor & = 0x0000FFFF; y no hará lo que se espera.

Por un lado, el valor no se inicializa antes de hacer el y, por lo tanto, creo que el comportamiento no está definido, el valor podría ser cualquier cosa.


Si bien se podría argumentar que, dado que no es un desbordamiento de búfer o algún otro error que pueda explotarse, es una cuestión de estilo y no un error, estoy 99% seguro de que la respuesta que está buscando el interrogador es que value se opera antes de que se asigne a. El valor va a ser basura arbitraria, y eso es poco probable que sea lo que se quiso decir, por lo que es "potencialmente incorrecto".


Usando MSVC, creo que la declaración realizaría lo que probablemente se pretendía, es decir: borrar todos los 16 bits de valor menos significativos, pero me he encontrado con otras plataformas que interpretarían el 0xffff literal como equivalente a (corto) -1, luego sign se extiende para convertir a long, en cuyo caso la declaración "value & = 0xFFFF" no tendrá efecto. "value & = 0x0FFFF" es más explícito y robusto.


Varias respuestas aquí indican que si un int tiene un ancho de 16 bits, 0xFFFF es negativo. Esto no es verdad. 0xFFFF nunca es negativo.

Un literal hexadecimal está representado por el primero de los siguientes tipos que es lo suficientemente grande como para contenerlo: int , unsigned int , long y unsigned long .

Si int tiene un ancho de 16 bits, entonces 0xFFFF es mayor que el valor máximo representable por un int . Por lo tanto, 0xFFFF es de tipo unsigned int , que se garantiza que es lo suficientemente grande como para representar 0xFFFF .

Cuando se realizan las conversiones aritméticas habituales para la evaluación de la & , el unsigned int se convierte en un long . La conversión de un unsigned int 16 bits a long está bien definida porque cada valor representable por un unsigned int 16 bits también es representable por un long 32 bits.

No se necesita una extensión de signo porque el tipo inicial no está firmado, y el resultado de usar 0xFFFF es el mismo que el resultado de usar 0xFFFFL .

Alternativamente, si int es más ancho que 16 bits, entonces 0xFFFF es de tipo int . Es un número firmado, pero positivo. En este caso, ambos operandos están firmados, y long tiene el mayor rango de conversión, por lo que la conversión aritmética habitual promueve nuevamente el int a long .

Como han dicho otros, debe evitar realizar operaciones bitwise en operandos firmados porque el resultado numérico depende de cómo se representa la firmeza.

Aparte de eso, no hay nada particularmente malo con este código. Yo diría que es una preocupación de estilo el hecho de que el value no se inicializa cuando se declara, pero probablemente sea un comentario de nivel de selección y depende del contenido de la //some stuff sección de //some stuff que se omitió.

Probablemente también es preferible usar un tipo entero de ancho fijo (como uint32_t ) en lugar de long para una mayor portabilidad, pero en realidad eso también depende del código que está escribiendo y de cuáles son sus suposiciones básicas.


Asumiré que es porque no hay un tamaño predefinido por mucho tiempo, aparte de que debe ser al menos tan grande como el tamaño anterior (int). Por lo tanto, dependiendo del tamaño, puede truncar el valor en un subconjunto de bits (si es más largo que más de 32 bits) o desbordar (si es menos de 32 bits).

Sí, los largos (según la especificación, y gracias por el recordatorio en los comentarios) deben poder contener al menos -2147483647 a 2147483647 (LONG_MIN y LONG_MAX).