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:
- Esta firmado
- 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).