C número entero comportamiento de desbordamiento cuando se asignan a los números enteros más grande de ancho
-
05-09-2019 - |
Pregunta
Si ejecuto el siguiente código en C:
#include <stdint.h>
uint16_t a = 4000;
uint16_t b = 8000;
int32_t c = a - b;
printf("%d", c);
Se imprime correctamente '-4000' como el resultado. Sin embargo, estoy un poco confundido: ¿no debería haber un desbordamiento aritmético al restar un entero sin signo más grande de la otra? ¿Qué reglas de fundición están en juego aquí? Esta pregunta parece un poco noobish, por lo que cualquier referencia sería muy apreciada.
Solución
La cuestión es en realidad un tanto complicado. Operandos de expresiones aritméticas se convierte usando las reglas específicas que se pueden ver en la Sección 3.2.1.5 de la estándar (C89) . En su caso, la respuesta depende de qué tipo es uint16_t
. Si es menor que int
, short int
decir, a continuación, los operandos se convierten a int
y se obtiene -4000, pero en un sistema de 16 bits, uint16_t
podría unsigned int
y la conversión a un tipo firmado no sucedería automáticamente.
Otros consejos
La respuesta corta es que todos estos son promovidos a int
durante la resta. Para la respuesta larga, mira la sección 6.3.1.1 de la C norma, donde se habla de promociones entero en expresiones aritméticas. idioma correspondiente de la norma:
Si un
int
puede representar todos los valores de el tipo original, el valor es convertida a unint
; de lo contrario, es convertida a ununsigned int
. Estas son llamados los promociones enteros . Todos los demás tipos no se han modificado por el promociones entero.
Los datos están ahí, también, pero consiguen bastante desagradable.
Los dos operandos son promovidos a int32_t
durante la resta. Si el resultado hubiera sido mayor que el valor máximo para int32_t
que podría haber obtenido desbordamiento.
Hay, de hecho, un desbordamiento pero C no te dice.
El desbordamiento deja un valor que pasa a ser -4000 cuando se interpreta como un número entero con signo. Esto funciona como se diseñó en las máquinas de complemento a 2.
Trate de interpretar el resultado como sin firmar, y se dará cuenta de que (u1-u2) evalúa a un número aparentemente sin relación, cuando U1