2012-04-01 5 views
13

почему d не равно b в этом примере?странный результат расчета

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 

Я использую Visual Studio 2008, Windows XP, core2duo. Спасибо.

+6

... Потому что d == c/1000. Это настоящая жизнь? – outis

+2

@crushanator На самом деле, а также не равно d. Ты это видел? –

+3

Почему в этом примере 1 не равно 2: 'int a = 1; int b = 2; '? –

ответ

5

Похоже, вы используете платформу, где int и long имеют одинаковый размер. (Я вывод, это тот факт, что если long был в состоянии держать все действительные значения unsigned int вы не видите поведение, которое вы видите.)

Это означает, что в выражении a*z, как a и z преобразуются в unsigned long, а результат имеет тип unsigned long. (ISO/IEC 14882: 2011, 5 [expr]/9 ... "В противном случае оба операнда должны быть преобразованы в целочисленный тип без знака, соответствующий типу операнда со знаком целочисленного типа.")

c результат преобразования этого выражения из unsigned long в long, и в вашем случае это приведет к результату, определенному реализацией (который является отрицательным), поскольку положительное значение a*z не может быть представлено в подписанном long. В c/1000, 1000 преобразуется в long и long деление выполнено (без каламбура), что приводит к long (что отрицательно) и сохраняется в d.

В выражениях a*z/1000, 1000 (выражение типа int) преобразуется в unsigned long и разделение выполняется между двумя unsigned long приводит к положительному результату. Этот результат представляется как long, и значение не изменяется при преобразовании в long и сохраняется до b.

+0

Это на самом деле дело в компиляторе MS C. – Inisheer

+0

Подписанное переполнение - это неопределенное поведение, но путь. –

+1

@KerrekSB: Да, но в этом примере нет подписанного переполнения. –

Смежные вопросы