2009-04-08 26 views
7

Si ejecuto el siguiente código en C:C número entero comportamiento de desbordamiento cuando se asignan a números enteros más grande de ancho

#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 más grande sin signo del otro? ¿Qué reglas de lanzamiento están en juego aquí? Esta pregunta parece un poco noobish, por lo que cualquier referencia sería muy apreciada.

Respuesta

5

El problema es realmente algo complicado. Los operandos de expresiones aritméticas se convierten utilizando reglas específicas que se pueden ver en la Sección 3.2.1.5 del Standard (C89). En su caso, la respuesta depende de lo que es el tipo uint16_t. Si es menor que int, digamos short int, entonces los operandos se convierten a int y obtiene -4000, pero en un sistema de 16 bits, uint16_t podría ser unsigned int y la conversión a un tipo firmado no ocurriría automáticamente.

+0

Mi referencia es, por supuesto, al viejo estándar. Ver la respuesta de tgamblin para C99. Aunque dicen lo mismo. – TrayMan

+0

3.2.1.5 es para conversiones double/float/int/etc. Está buscando promociones integrales (long/int/char/short/etc) que se encuentran en 3.2.1.1 de esa versión del estándar. Está en 6.3.1.1 en el estándar más nuevo al que he vinculado anteriormente. – tgamblin

+0

También podría querer 3.2.1.2 también (entradas/salidas sin firmar) – tgamblin

1

Ambos operandos se promueven a int32_t durante la resta. Si el resultado hubiera sido mayor que el valor máximo para int32_t, habría visto desbordamiento.

3

La respuesta corta es que todos estos se promocionan a int durante la resta. Para la respuesta larga, consulte la sección 6.3.1.1 del C standard, donde se habla de promociones enteras en expresiones aritméticas. idioma correspondiente de la norma:

Si un int puede representar todos los valores de el tipo original, el valor es convierte a un int; de lo contrario, es convertido a unsigned int. Estos se llaman promociones enteras . Todos los demás tipos no se modifican mediante las promociones enteras .

Los detalles están ahí, también, pero se ponen bastante desagradables.

0

Hay, de hecho, un desbordamiento, pero C no le dice nada.

El desbordamiento deja un valor que resulta ser -4000 cuando se interpreta como un entero con signo. Esto funciona como está diseñado en máquinas de complemento a 2.

Intente interpretar el resultado como no firmado, y verá que (u1-u2) se evalúa como un número aparentemente no relacionado cuando u1 < u2.

Cuestiones relacionadas