2011-07-07 17 views
8

echa un vistazo a esto. El compilador se queja de que tengo un desbordamiento de enteros, pero cuando miro las reglas del estándar C89 para la promoción integral junto con los valores en esa expresión, me parece que no hay desbordamiento.C ¿Desbordamiento integral?

[email protected]:~$ cat test.c 
#include <stdio.h> 
#include <inttypes.h> 

const uint32_t value = 
    (0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256) + 
    (0xDF-0xC2 + 1) * (256 + 256*256 + 256*256*256); 

int 
main(void) 
{ 
    printf("value = %"PRIu32"\n", value); 
    return 0; 
} 
[email protected]:~$ gcc -std=c89 -pedantic -Wall -Wextra test.c 
test.c:5: warning: integer overflow in expression 
test.c:6: warning: integer overflow in expression 
test.c:6: warning: overflow in constant expression 
[email protected]:~$ ./a.out 
value = 2661195264 
[email protected]:~$ 

Por otra parte, Google confirma que la respuesta de la 2661195264 es el valor correcto para esa expresión! (See this link)

Entonces, ¿cómo es que el programa puede producir un valor correcto cuando hubo desbordamiento de enteros? Y más importante aún, ¿cómo es que había un desbordamiento de enteros en esa expresión para empezar?

+0

Tal vez utiliza entradas firmadas en lugar de sin firmar, entonces se habría producido un desbordamiento en la operación firmada aunque se calculó el valor correcto sin firmar. – Nobody

Respuesta

14
(0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256) 

tiene el valor 2155905024; el más grande representable con 32-bit int es 2147483647, por lo que ha producido un desbordamiento. De todos modos, le dio el resultado esperado (tuvo suerte).

cuenta que todo el inicializador tiene firmaron tipo (tipo int, específicamente), ya que ninguno de los literales se añade como sufijo. La expresión se evalúa como un int firmado, luego el valor resultante se convierte en un entero sin signo.

+2

... y tenga en cuenta que 'int' solo tiene que ser de 16 bits, por lo que incluso' 256 * 256' es potencialmente un desbordamiento. Puede corregir esto usando '256UL' en lugar de' 256' para cada una de esas constantes. – caf

2

Aunque sus constantes son todas positivas, siguen siendo enteros con signo. Estás desbordando el rango de un entero con signo. El resultado se convierte en unsigned como el último paso cuando se asigna a la variable.

Los patrones de bits para sumar, restar y multiplicar son idénticos entre operaciones con signo y sin signo. Si bien el compilador no está obligado a proporcionar la respuesta correcta en este caso, es simplemente el resultado más natural.

Cuestiones relacionadas