2010-03-01 5 views
14

Estoy pasando por un montón de preguntas de la entrevista de C++ solo para asegurarme de que no haya nada obvio que yo no sé. Hasta el momento no he encontrado nada que no sabía ya, salvo esto:Respuesta a una pregunta de la entrevista de práctica

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

La pregunta es "¿qué hay de malo con este código" Y sugiere que se trata de algo relacionado con las arquitecturas de destino.

A menos que la respuesta sea solo "el valor no se ha inicializado", no puedo ver ningún problema. Por lo que puedo decir, solo está enmascarando los 2 bytes menos significativos del valor, y se garantiza que long tendrá al menos 2 bytes, por lo que no hay ningún problema.

¿Es posible que long solo tenga 2 bytes en la arquitectura de destino y es posible que pierda el bit de signo? O tal vez que el 0xFFFF es un int y int tiene solo 2 bytes?

Gracias de antemano.

+6

No trabajaría para un empleador que requiera responder preguntas tan vagas. No es un problema de endianess (las diferencias de endianess no aparecen en aritmética), sino una extensión de signo, que le di +1 a John Knoeller. En general, es una buena idea hacer todas las operaciones de bits sin firmar para evitar problemas inesperados como este. – Tronic

+0

Observe que 'long' tiene al menos 32 bits. En las plataformas de 8 bits, eso es 4 bytes (por supuesto, eso todavía puede causar problemas de firma para no-2complementos). –

+0

¿Qué pasó con tu respuesta, Johannes? –

Respuesta

15

Este problema con este código es que hace una operación poco sabia en un valor firmado. Los resultados de tales operaciones en valores negativos varían mucho para diferentes representaciones enteras.

Por ejemplo, consideremos el siguiente programa:

#include <iostream> 

int main(void) 
{ 
    long value; 
    value = -1; // Some stuff 
    value &= 0xffff; 
    std::cout << "Value = " << value << std::endl; 
} 

en una arquitectura de complemento a dos el resultado es:

Value = 65535 

en una arquitectura one's-complemento, el resultado es:

Value = 65534 

En una arquitectura de signo y magnitud el resultado es:

Value = 1 
+2

Exactamente. Vea este informe CERT: https://www.securecoding.cert.org/confluence/display/seccode/INT13-C.+Use+bitwise+operators+only+on+unsigned+operands. En particular, de acuerdo con el estándar C (como se hace referencia allí), los resultados de las operaciones bit a bit en los valores firmados están definidos por la implementación. –

-1

suena como Big-Endian vs. Little-Endian para mí. http://en.wikipedia.org/wiki/Endianness

+4

Altamente improbable que sea endianness dado este pequeño contexto. Para que sea un problema de endianness, tendría que haber una operación de 'dirección de' allí, o algo así. –

+2

La operación del valor-contexto no depende de la endianidad. Es imposible "ver" endianness en C++ hasta que comiences a inspeccionar la memoria [raw]. – AnT

7

Es difícil saber lo que el entrevistador esperaba que dijera. Tenemos que adivinar.

Supongo que en algunas arquitecturas, 0xFFFF será un valor firmado de 16 bits, mientras que long es un valor firmado de 32 bits. Cuando extiendes la constante para que se pueda usar para enmascarar el valor largo, el signo se extenderá y se convertirá en 0xFFFFFFFFl, que no es lo que pretendías en absoluto.

Adición: El código como obras escritas correctamente en los tres de los compiladores que uso actualmente, así que esto es de hecho un juego de adivinanzas de tratar de averiguar lo que el entrevistador pretende. Un compilador de 16 bits que cumpla con los estándares también generaría el código correcto, por lo que nos quedamos adivinando si hay algo que fallamos, si el ejemplo no está roto o si el entrevistador alguna vez usó un compilador de 16 bits que trataría 0xFFFF como una cantidad firmada cuando se lo fuerza a extenderlo a un largo. Sería interesante preguntarle.

+1

No es posible. En C++ '0xFFFF' no puede ser un valor firmado de 16 bits. Este valor no cabe en el rango del tipo de 16 bits firmado, lo que significa que el compilador tendrá que usar el tipo * unsigned * de 16 bits. – AnT

+0

Es un _guess_ chicos. Por lo que sabemos, el código no tiene nada de malo, y el entrevistador simplemente pensó que estaba mostrando un código dañado. –

+2

@ John Knoeller: No, lo que parece que no entiendes es que hay cosas de las que se puede esperar razonablemente que sean diferentes entre los compiladores (e incluso que no cumplan algunas veces), y hay cosas que razonablemente se espera que se implementen correctamente. * Este * es uno de los elementos que todos los compiladores implementan correctamente. Todos los compiladores que no obtuvieron este bit específico correctamente se rieron de la existencia hace mucho tiempo. En cualquier caso, una falla al implementar tal cosa fundamental correctamente de manera inmediata e indiscutible descalifica a un compilador de ser llamado "un compilador de C++". – AnT

1

¡Puedo decir, no hay nada de malo en este código a menos que se conozca el contexto o la intención del código que lo rodea!

+1

Bueno, no escribí esto en el OP, pero la pregunta realmente preguntaba "¿qué * podría ser * incorrecto con este código?", Así que realmente te estoy pidiendo que hagas algunas suposiciones sobre un contexto razonable. –

0

Esto podría ser un tiro en la oscuridad, pero suponiendo que el largo vs int no es el problema (otros han publicado respuestas que respondan precisamente eso) y que el 0xFFFF abarca la cantidad total requerida por el tipo, ¿no sería esto? solo está haciendo value = 0xFFFF y no hay necesidad de manipular el bit? ¿No es redundante la manipulación de bits?

La única otra cosa que puedo ver es si la persona que hizo la pregunta quería que se diese cuenta de que los datos faltantes contenidos en el tiempo no se verían afectados por el uso de 0xFFFF.

Para mí viene a ser un poco loco de una pregunta que hacer sobre la base de cómo se presenta aquí la pregunta o tal vez es sólo tan obvio que estamos sobre el pensamiento todo lo que :)

+1

Porque el uso de 'operator & =' no asigna ese valor a la variable. Se ANDs los bits junto con lo que ya está en la variable, no importa lo que es eso. Si 'value' contiene' 0xDEAD', seguirá conteniéndolo después de la llamada a 'operator & ='. –

0

Sospecho que todos estamos pensando demasiado.

Lo que está mal con este código es que el valor no se inicializa. La pregunta es: ¿se da cuenta de que el & = (o + =, - =/= etc.) no tiene sentido cuando se usa en un valor unificado?

Si el valor se inicializa, entonces el comportamiento está bien definido. Los 16 bits menos significativos se conservan, el resto se ponen a cero

+0

Creo que todos están asumiendo que '// algunas cosas' tiene inicialización variable. – Tanzelax

+0

La sugerencia indica que es algo que puede salir mal en una arquitectura inusual, por lo que dudo que sea una inicialización, y dudo que el & = no sea relevante. –

+0

entonces mi segundo comentario se mantiene - si el valor se inicializa, entonces el comportamiento está bien definido – pm100

Cuestiones relacionadas