c - tipos - ¿Por qué un int negativo es mayor que unsigned int?
unsigned int para que sirve (6)
Cuando compara dos valores en C, ambos deben ser del mismo tipo. En este caso ( int
y unsigned int
), el valor int
se convertirá primero en unsigned int
.
En segundo lugar, la aritmética de enteros sin signo en C se realiza en módulo del valor máximo de ese tipo + 1 (es decir, "gira alrededor", por lo que UINT_MAX + 1
vuelve a ser 0
y viceversa). Por lo tanto, convertir valores negativos a resultados sin firmar en números muy grandes.
La sección relevante en el estándar dice:
6.3.1.3 enteros con signo y sin signo
2
De lo contrario, si el nuevo tipo no está firmado, el valor se convierte al agregar o restar repetidamente uno más que el valor máximo que se puede representar en el nuevo tipo hasta que el valor esté en el rango del nuevo tipo.
Esta pregunta ya tiene una respuesta aquí:
int main(void)
{
unsigned int y = 10;
int x = – 4;
if (x > y)
Printf("x is greater");
else
Printf("y is greater");
getch();
return (0);
}
Output: x is greater
Pensé que la salida sería y es mayor ya que no está firmado. ¿Cuál es la razón detrás de esto?
Cuando compara una int
y una unsigned int
int
se convierte en unsigned int
. La conversión de un int
a un unsigned int
se hace agregando UINT_MAX+1
(tenga en cuenta que su int
es negativo). Entonces en realidad estás comparando:
if (-3 + UINT_MAX > 10) //Since -4 is converted to UINT_MAX+1-4
Cual es verdad.
El primer bit de un valor int se usa para definir si es positivo o negativo. (1 = negativo, 0 positivo) Sus dos variables se convierten en int sin signo antes de la comparación, donde el 1 en el primer bit se interpretará como parte de su número.
este código debería funcionar bien:
int main(void)
{
unsigned int y = 10;
int x = – 4;
if (x > (int) y)
Printf("x is greater");
else
Printf ("y is greater");
getch ( );
return (0);
}
Porque el valor int
se promueve a un unsigned int
. específicamente 0xFFFFFFFC
en una máquina de 32 bits, que como unsigned int
es 4294967292
, considerablemente más grande que 10
C99 6.3.1.1-p2
Si un int puede representar todos los valores del tipo original (como está restringido por el ancho, para un campo de bit), el valor se convierte en un int; de lo contrario, se convierte a unsigned int . Estas se llaman promociones enteras. Todos los otros tipos no se modifican por las promociones enteras.
Para realizar la conversión:
C99 6.3.1.3-p2
De lo contrario, si el nuevo tipo no está firmado, el valor se convierte al agregar o restar repetidamente uno más que el valor máximo que se puede representar en el nuevo tipo hasta que el valor esté en el rango del nuevo tipo.
Lo que básicamente significa "agregar UINT_MAX + 1" (como lo leí, de todos modos).
En cuanto a por qué la promoción fue al lado unsigned int
; precedencia:
C99 6.3.1.8-p1
... De lo contrario, si el operando que tiene un tipo entero sin signo tiene un rango mayor o igual al rango del tipo del otro operando, entonces el operando con tipo entero con signo se convierte al tipo del operando con tipo entero sin signo.
De lo contrario, si el tipo del operando con tipo entero con signo puede representar todos los valores del tipo del operando con tipo entero sin signo, entonces el operando con tipo entero sin signo se convierte al tipo del operando con tipo entero con signo.
Lo que me dice que int
frente a unsigned char
debería funcionar como se esperaba.
Prueba
int main()
{
int x = -4;
unsigned int y = 10;
unsigned char z = 10;
if (x > y)
printf("x>y/n");
else
printf("x<y/n");
if (x > z)
printf("x>z/n");
else
printf("x<z/n");
return 0;
}
Salida
x>y
x<z
Bueno, mira eso.
Se realizará una comparación entre un valor con signo y sin signo en "espacio sin signo". Es decir, el valor firmado se convertirá a sin firmar agregando UINT_MAX + 1
. En la implementación que usa el complemento 2 para valores negativos, no se requiere un manejo especial de los valores bajo el capó.
En este ejemplo, el -4
se convierte en un 0x100000000-4
= 0xFFFFFFFC
que es claramente > 10
.
int x = -4 (el complemento a 2 de 4 es 1111 1100 = 252) y sin signo int y = 10 es (0000 1010 = 10) entonces 252> 10 entonces -4 es mayor que 10.