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.
Спасибо.
Ответ 1
Похоже, вы используете платформу, где 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.