trabajo - programa de preguntas y respuestas en c++
Pregunta de la entrevista (8)
Me preguntaron la salida del siguiente código en mi entrevista de ayer.
#include <stdio.h>
int main(void){
printf ("%x" ,-1<<4);
}
Me dieron 2 minutos para decir la respuesta. Respondí fffffff0
. El resultado de la entrevista aún no ha sido declarado. Quiero saber si mi respuesta fue correcta?
Acabo de escribir el código en un archivo de texto, lo compilé y SÍ , la respuesta es correcta.
Ejecuté este código en 3 compiladores y sistemas operativos diferentes. Todos me dieron esta misma respuesta como se menciona en la pregunta. Hasta ya menos que a alguien se le ocurriera el compilador en el que este es un comportamiento realmente indefinido, diré que la respuesta es CORRECTA. Si esto es estable en el 99,99% de las situaciones, entonces hay más posibilidades de que se cambie el estándar, que el compilador deje de admitirlo.
El desplazamiento a la izquierda de un número negativo no está definido para el caso general , pero debemos entender por qué este comportamiento indefinido (UB)? Tenga en cuenta que el bit más significativo (MSb) es el bit de signo. Si este bit es un 1, el número es negativo. Si es un cero, el número es positivo. Esta es información crítica que se pierde con el primer turno a la izquierda. Por ejemplo
-32768<<4
es lo mismo que
0x8000<<4
(asumiendo una máquina de 16 bits por simplicidad)
El resultado es, por supuesto, 0, que realmente no tiene ningún sentido y por lo tanto es UB.
En el caso específico de la pregunta de la entrevista del OP, solo nos preocupa un valor específico ... no es el caso general. -1 (0xffffffff en una máquina de 32 bits) desplazado a la izquierda 4 veces producirá 0xfffffff0 como el OP originalmente pensó.
En mi máquina:
chris@zack:~$ cat > test.c
#include <stdio.h>
int main(void){
printf ("%x" ,-1<<4);
}
chris@zack:~$ gcc -o test test.c && ./test
fffffff0
Sin embargo, el resultado dependerá de su arquitectura y compilador. Así que la respuesta correcta es "podría producir cualquier cosa".
Es un comportamiento indefinido.
$ cat undef.c
#include <stdio.h>
int main(void){
printf ("%x" ,-1<<4);
}
$ clang -fsanitize=undefined undef.c
$ ./a.out
undef.c:3:24: runtime error: left shift of negative value -1
fffffff0
No. No estás en lo correcto. Esa es la mala noticia. La buena noticia es que el entrevistador probablemente no lo sepa y asumirá que lo eres porque es el resultado que ELLOS obtienen cuando lo compilan y lo ejecutan.
La respuesta verdadera es que es la implementación definida. No estoy 100% seguro de decir que es un comportamiento indefinido debido a la sobrecarga, pero creo que puede ser. Como mínimo, aunque el resultado depende de cómo se representan los números negativos, etc ... Ninguno de los dos idiomas que ha afirmado está en definir cuál será la salida.
Técnicamente, el desplazamiento a la izquierda de un entero negativo invoca un comportamiento indefinido. Eso significa que -1<<4
es UB. No sé por qué te hicieron esta pregunta. Probablemente quisieron probar su conocimiento profundo de los Estándares C y C ++.
C99 [ 6.5.7/4
] dice
El resultado de E1 << E2 es E1 posiciones de bit E2 desplazadas a la izquierda; los bits desocupados se llenan con ceros. Si E1 tiene un tipo sin signo, el valor del resultado es E1 × 2 E2 , módulo reducido uno más que el valor máximo representable en el tipo de resultado. Si E1 tiene un tipo con signo y un valor no negativo, y E1 × 2 E2 se puede representar en el tipo de resultado, ese es el valor resultante; de lo contrario, el comportamiento no está definido .
C ++ 03 lo convierte en un comportamiento indefinido al omitir el texto relevante .
Binary of 1 : 0000 0000 0000 0000 0000 0000 0000 00001
Reemplace la ocurrencia de 0 por 1 ya que va a calcular el binario de no negativo
Cómo calcular binarios de números negativos.
Binary of -1 : 1111 1111 1111 1111 1111 1111 1111 11111
Left shift 4 : 1111 1111 1111 1111 1111 1111 1111 0000
La representación hexagonal de la izquierda resultante 4 será
1111 : F
0000 : 0
entonces la salida calculada será:
FFFFFFF0
Tu respuesta es correcta.