Operación de comparación en enteros sin signo y con signo


Ver este fragmento de código

int main()
{ 
 unsigned int a = 1000;
 int b = -1;
 if (a>b) printf("A is BIG! %d\n", a-b);
 else printf("a is SMALL! %d\n", a-b); 
 return 0;
}   

Esto da la salida: a es PEQUEÑA: 1001

No entiendo lo que está pasando aquí. ¿Cómo funciona el > operator aquí? ¿Por qué la "a "es más pequeña que la"b"? Si de hecho es más pequeño, ¿por qué obtengo un número positivo (1001) como la diferencia?

Author: R Sahu, 2010-01-18

7 answers

Las operaciones binarias entre diferentes tipos de integrales se realizan dentro de un tipo "común" definido por las llamadas conversiones aritméticas usuales (ver la especificación del lenguaje, 6.3.1.8). En su caso el tipo" común " es unsigned int. Esto significa que el operando int (su b) se convertirá a unsigned int antes de la comparación, así como con el propósito de realizar resta.

Cuando -1 se convierte a unsigned int el resultado es el valor máximo posible unsigned int (igual que UINT_MAX). No hace falta decir que va a ser mayor que su valor sin signo 1000, lo que significa que a > b es de hecho falso y a es de hecho pequeño comparado con (unsigned) b. El if en su código debe resolver a la rama else, que es lo que observó en su experimento.

Las mismas reglas de conversión se aplican a la resta. Su a-b se interpreta realmente como a - (unsigned) b y el resultado tiene el tipo unsigned int. Dicho valor no se puede imprimir con %d especificador de formato, ya que %d solo funciona con valores firmados. Su intento de imprimirlo con %d resulta en un comportamiento indefinido, por lo que el valor que ve impreso (a pesar de que tiene una explicación determinista lógica en la práctica) carece completamente de sentido desde el punto de vista del lenguaje C.

Edit: En realidad, podría estar equivocado sobre la parte de comportamiento indefinido. De acuerdo con la especificación del lenguaje C, la parte común del rango del tipo entero con y sin signo correspondiente deberá tener representación idéntica (lo que implica, según la nota 31, "intercambiabilidad como argumentos a funciones"). Por lo tanto, el resultado de la expresión a - b es unsigned 1001 como se describió anteriormente, y a menos que me falte algo, es legal imprimir este valor específico sin signo con %d especificador, ya que cae dentro del rango positivo de int. Impresión (unsigned) INT_MAX + 1 con %d sería indefinido, pero 1001u está bien.

 44
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-27 14:01:33

En una implementación típica donde int es de 32 bits, -1 cuando se convierte a un unsigned int es 4,294,967,295 que es de hecho ≥ 1000.

Incluso si tratas la resta en un mundo unsigned, 1000 - (4,294,967,295) = -4,294,966,295 = 1,001 que es lo que obtienes.

Es por eso que gcc escupirá una advertencia cuando compare unsigned con signed. (Si no ve una advertencia, pase la bandera -Wsign-compare.)

 13
Author: kennytm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-09 13:01:05

Está haciendo una comparación sin signo, es decir, comparando 1000 a 2^32 - 1.

La salida está firmada debido a %d en printf.

N.B. A veces el comportamiento al mezclar operandos firmados y sin firmar es específico del compilador. Creo que es mejor evitarlos y hacer yesos en caso de duda.

 0
Author: Antti Huima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-18 09:45:14

Encuentre una manera fácil de comparar, tal vez útil cuando no puede deshacerse de la declaración sin firmar, (por ejemplo, [NSArray count]), solo fuerce el "int sin firmar" a un "int".

Por favor corríjame si estoy equivocado.

if (((int)a)>b) {
    ....
}
 0
Author: chenyi1976,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-02 13:07:29

El hardware está diseñado para comparar firmado con firmado y sin firmar con sin firmar.

Si desea el resultado aritmético, convierta primero el valor sin signo a un tipo con signo más grande. De lo contrario, el compilador asumirá que la comparación es realmente entre valores sin signo.

Y -1 se representa como 1111..1111, por lo que una cantidad muy grande ... El más grande ... Cuando se interpreta como sin signo.

 0
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-20 05:26:17
 #include<stdio.h>
 int main()
 {
   int a = 1000;
   signed int b = -1, c = -2;
   printf("%d",(unsigned int)b);
   printf("%d\n",(unsigned int)c);
   printf("%d\n",(unsigned int)a);

   if(1000>-1){
      printf("\ntrue");
   }
   else 
     printf("\nfalse");
     return 0;
 }

Para esto es necesario entender la precedencia de los operadores

  1. Los operadores relacionales funcionan de izquierda a derecha ... así que cuando se trata

    If (1000>-1)

Entonces primero de todo cambiará -1 a entero sin signo porque int se trata por defecto como número sin signo y lo rango mayor que el número con signo

-1 cambiará al número sin signo ,cambia a un número muy grande

 0
Author: harsh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-12 12:30:55

Al comparar a > b donde a es tipo int sin signo y b es tipo int, b es tipo fundido a int sin signo por lo tanto, el valor int con signo -1 se convierte en el valor MÁXIMO de unsigned * * (rango: 0 a (2^32)-1 )** Por lo tanto, a>b es decir, (1000>4294967296) se convierte en falso. Por lo tanto else loop printf ("a is SMALL! % d\n", a-b); ejecutado.

 -1
Author: Naveen Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-09 22:36:27