Похоже, вы используете платформу, где 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
.
... Потому что d == c/1000. Это настоящая жизнь? – outis
@crushanator На самом деле, а также не равно d. Ты это видел? –
Почему в этом примере 1 не равно 2: 'int a = 1; int b = 2; '? –