
Guantánamo
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ÑO: 1001
No entiendo lo que está pasando aquí. ¿Cómo funciona aquí el operador >? ¿Por qué “a” es más pequeña que “b”? Si es más pequeño, ¿por qué obtengo un número positivo (1001) como diferencia?

Hormiga
Las operaciones binarias entre diferentes tipos integrales se realizan dentro de un tipo “común” definido por los llamados conversiones aritméticas habituales (ver la especificación de idioma, 6.3.1.8). En su caso, el tipo “común” es unsigned int
. Esto significa que int
operando (su b
) se convertirá en unsigned int
antes de la comparación, así como con el fin de realizar la resta.
Cuando -1
se convierte en unsigned int
el resultado es el máximo posible unsigned int
valor (igual que UINT_MAX
). No hace falta decir que va a ser mayor que su no firmado 1000
valor, lo que significa que a > b
de hecho es falso y a
es de hecho pequeña comparado con (unsigned) b
. Él if
en su código debe resolver a else
rama, que es lo que observaste en tu 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 tipo unsigned int
. Dicho valor no se puede imprimir con %d
especificador de formato, ya que %d
solo funciona con firmado valores. Su intento de imprimirlo con %d
da como resultado un comportamiento indefinido, por lo que el valor que ve impreso (aunque tiene una explicación lógica determinista en la práctica) no tiene ningún sentido desde el punto de vista del lenguaje C.
Editar: En realidad, podría estar equivocado sobre la parte del comportamiento indefinido. De acuerdo con la especificación del lenguaje C, la parte común del rango del tipo de entero con signo y sin signo correspondiente debe tener una representación idéntica (lo que implica, según la nota al pie 31, “intercambiabilidad como argumentos para funciones”). Entonces, el resultado de a - b
la expresión no está firmada 1001
como se describe arriba, y a menos que me falte algo, es legal imprimir este valor específico sin firmar 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.

kennytm
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 unsigned
mundo, 1000 - (4,294,967,295) = -4,294,966,295 = 1,001
que es lo que obtienes.
Es por eso gcc
escupirá una advertencia cuando compares unsigned
con signed
. (Si no ve una advertencia, pase el -Wsign-compare
bandera.)
#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 necesitas entender la precedencia de los operadores.
-
Los operadores relacionales funcionan de izquierda a derecha… así que cuando se trata
si (1000>-1)
luego, en primer lugar, cambiará -1 a un entero sin signo porque int se trata de forma predeterminada como un número sin signo y su rango es mayor que el número con signo
-1 cambiará al número sin firmar, cambia a un número muy grande

antti huima
Está haciendo una comparación sin signo, es decir, comparando 1000 con 2^32 – 1.
La salida está firmada debido a %d en printf.
NB: a veces, el comportamiento cuando mezcla operandos firmados y no firmados es específico del compilador. Creo que es mejor evitarlos y hacer yesos en caso de duda.
Encuentre una manera fácil de comparar, tal vez útil cuando no puede deshacerse de la declaración sin firmar (por ejemplo, [NSArray count]), simplemente fuerce el “int sin firmar” a un “int”.
Por favor, corríjame si estoy equivocado.
if (((int)a)>b) {
....
}

DigitalRoss
El hardware está diseñado para comparar firmado con firmado y sin firmar con sin firmar.
Si desea el resultado aritmético, primero convierta 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 es una cantidad muy grande… La más grande… Cuando se interpreta como sin signo.

naveen kumar
al comparar a>b donde a es de tipo int sin signo y b es de tipo int, b es tipo casted a unsigned int por lo tanto, el valor int firmado -1 se convierte en el valor MAX de unsigned**(rango: 0 a (2^32)-1)** Por lo tanto, a>b, es decir, (1000>4294967296) se vuelve falso. Por lo tanto, el bucle más printf(“a es PEQUEÑO! %d\n”, ab); ejecutado.
Si usa el indicador del compilador -Wsign-compare, recibirá una advertencia para la comparación. Siempre debe usar -Wall (que incluye -Wsign-compare). Ver aquí para conocer otras formas de evitar este problema.
– Alejandro
5 de diciembre de 2010 a las 20:58
Consulte esta publicación para obtener más información: stackoverflow.com/q/10474769/844882
– Adrián Monk
7 de mayo de 2012 a las 1:44
@ Aleph7 – técnicamente eso no es del todo correcto, -Wsign-compare es solo inc. con -Pared Si Estás compilando C++. No está incluido para C (ver aquí gcc.gnu.org/onlinedocs/gcc/Warning-Options.html) Lo probé y puedo confirmar que el código anterior no da ninguna advertencia con -Wall pero sí con -Wsign-compare (estoy usando gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010)
– bph
10 de noviembre de 2016 a las 20:09