2012-04-01 10 views
13

¿por qué d no es igual a b en este ejemplo?resultado de cálculo extraño

unsigned int z = 176400; 
    long a = -4; 
    long b = a*z/1000; //b=4294261 
    long c = a*z; // c=-705600 
    long d = c/1000; // d =-705 

Uso Visual Studio 2008, Windows XP, core2duo. Gracias.

+6

... Porque d == c/1000. ¿Es esto una vida real? – outis

+2

@crushanator De hecho, a tampoco es igual a d. ¿Viste eso? –

+3

¿Por qué 1 no es igual a 2 en este ejemplo? 'Int a = 1; int b = 2; '? –

Respuesta

5

Parece que está utilizando una plataforma donde int y long tienen el mismo tamaño. (He deducido esto por el hecho de que si long fue capaz de mantener todos los valores válidos de unsigned int que no podría ver el comportamiento que usted está viendo.)

Esto significa que en la expresión a*z, tanto a y z se convierten a unsigned long y el resultado tiene el tipo unsigned long. (ISO/IEC 14882: 2011, 5 [expr]/9 ... "De lo contrario, ambos operandos se convertirán al tipo de entero sin signo correspondiente al tipo del operando con tipo entero con signo.")

c es el resultado de convertir esta expresión de unsigned long a long y en su caso esto resulta en un resultado definido de implementación (que pasa a ser negativo) ya que el valor positivo de a*z no es representable en un long firmado. En c/1000, 1000 se convierte en long y long se realiza la división (sin juego de palabras) lo que resulta en un long (que pasa a ser negativo) y se almacena en d.

En las expresiones a*z/1000, 1000 (una expresión de tipo int) se convierte en unsigned long y la división se lleva a cabo entre dos unsigned long que resulta en un resultado positivo. Este resultado es representable como long y el valor no se modifica al convertir a long y almacenarlo en b.

+0

Esto es de hecho el caso en el compilador MS C. – Inisheer

+0

Desbordamiento firmado es un comportamiento indefinido, pero el camino. –

+1

@KerrekSB: Sí, pero no hay desbordamiento firmado en este ejemplo. –