Pregunta

Véase 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 le da a la salida:una es PEQUEÑA:1001

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

¿Fue útil?

Solución

Las operaciones binarias entre diferentes tipos integrales se llevan a cabo dentro de un tipo "común" definido por los llamados conversiones aritméticas habituales (ver la especificación del lenguaje, 6.3.1.8). En el caso del tipo "común" es unsigned int. Esto significa que el operando int (su b) conseguirá convertido a unsigned int antes de la comparación, así como a los efectos de realizar la resta.

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

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

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

Otros consejos

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

Incluso si el tratamiento de la sustracción en un mundo unsigned, 1000 - (4,294,967,295) = -4,294,966,295 = 1,001 que es lo que obtienes.

Es por eso gcc escupirá una advertencia cuando se compara con unsigned signed. (Si no ve una advertencia, pase el indicador -Wsign-compare.)

Usted está haciendo la comparación sin signo, es decir, comparar 1000 a 2 ^ 32 -. 1

La salida está firmado por% d en printf.

N.B. a veces el comportamiento cuando se mezclan firmado y operandos sin signo es su compilador. Creo que lo mejor es evitarlos y hago arroja en caso de duda.

Encontrar una manera fácil de comparar, que puede resultar útil cuando no puede deshacerse de la declaración firmada, (por ejemplo, [recuento NSArray]), simplemente forzar el "unsigned int" a un "int".

Por favor, corríjanme si estoy equivocado.

if (((int)a)>b) {
    ....
}

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

Si desea que el resultado aritmético, convertir el valor sin signo a un tipo más grande firmado por primera vez. De lo contrario el compilador Wil asume que la comparación es realmente entre los 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 signo.

 #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 usted necesita para comprender la precedencia de los operadores

  1. Los Operadores relacionales de las obras de izquierda a derecha ...así que cuando se trata de

    si(1000>-1)

a continuación, en primer lugar se va a cambiar de -1 a unsigned int entero porque es por defecto tratados como número sin signo y el rango es mayor que el firmado número

-1 va a cambiar en el número sin signo ,se transforma en un muy gran número de

mientras que en comparación a> b donde a es unsigned int tipo y B es de tipo int, b está tipo fundido a unsigned int así, firmado int valor -1 se convierte en valor MAX de unsigned ** (intervalo: 0 a (2 ^ 32) -1) ** Por lo tanto, a> b es decir, (1000> 4294967296) se convierte en falsa. bucle más Por lo tanto printf ( "a es SMALL% d \ n", a-b);. ejecutado

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top