¿Por qué un int sin signo comparado con un carácter con signo se convierte en un resultado inesperado? [cerrado]

7

¿Por qué aparece el siguiente código y > x cuando claramente 1 > -1?

unsigned x=1;
signed char y=-1;

if(x>y){
    printf("x>y");
}
else {
    printf("y>x");
}

Por favor, explique este resultado.

    
pregunta Sudhir 09.11.2012 - 11:38

3 respuestas

10

La conversión de tipo implícita te está mordiendo. Como x no está firmado, y también se convierte en unsigned; porque -1 no encaja en un carácter sin signo, se desborda y se convierte en 255 (el equivalente en bits sin signo de -1), que obviamente es mayor que -1.

    
respondido por el tdammers 09.11.2012 - 11:50
2

La respuesta de @tdammers es correcta, déjame expandirte un poco.

La representación binaria para valores negativos asume que el bit más alto tiene un valor de 1 . Por ejemplo, todos los valores negativos de 8 bits se ven como 1xxx xxxx .

El valor de 8 bits para -1 es 1111 1111 .

Por lo tanto, el mismo binario 1111 1111 para sin firmar es 255 . Por lo tanto, el mismo valor binario se puede interpretar de dos maneras diferentes , dependiendo de si está firmado o no.

En su caso, como notó @tdammers, su -1 se almacena en la variable con signo , pero luego se interpreta implícitamente como sin signo . Por supuesto, 1 < 255 , de ahí el resultado.

P.S. Siempre debes revisar las advertencias del compilador. Todos los compiladores modernos emitirían una advertencia sobre este asunto.

    
respondido por el bytebuster 09.11.2012 - 12:47
1

Este es un caso en el que, con suerte, recibirá una advertencia del compilador sobre la mezcla de un valor firmado y sin signo. Puede ser aún más específico cuando se trata de un valor no firmado y un valor firmado.

Este ejemplo subraya los peligros de C y, en menor medida, de C ++ (que tiende a ser un poco más estricto con respecto a la verificación de tipos, y que ofrece múltiples tipos de modelos). Si desea escribir código C de buena calidad, varias cosas pueden ayudar:

  • Como precaución básica, use las opciones del compilador para generar las advertencias más estrictas posibles.
  • Muy específicamente, evite mezclar valores con y sin signo en las comparaciones y en la mayoría de los cálculos. (firmado = firmado * sin firmar OK, firmado = firmado + sin firmar OK, la mayoría de las demás mezclas, mal).
  • Use printf (), trace () o inspección de variables en un depurador para comprender mejor dónde van las cosas mal. Si su programa incluyó una declaración como printf ("x =% d, y =% d / n", x, y); verías que las cosas fueron mal como -1 se asignó a y.
  • Estudie, estudie, estudie ... C es un lenguaje exigente y debe hacerse lo más experto posible en la semántica y los efectos secundarios de las comparaciones y cálculos firmados y no firmados. También necesita un grado muy alto de atención al detalle sobre el rango de valores de entrada a las ecuaciones, el rango posible de resultados de las ecuaciones y si las constantes pueden encajar en las variables a las que están asignadas.
  • Cuando sea apropiado, utilice las técnicas de programación defensiva como aseveraciones para exponer los problemas de programación durante el desarrollo.
respondido por el DeveloperDon 09.11.2012 - 12:40

Lea otras preguntas en las etiquetas