int left = std::numeric_limits<int>::min();
int right = -1;
//the code below instead of give one more than int_max gives: 18446744071562067968
unsigned long long result = left * right;
Я пытался найти UAC, но даже в соответствии с правилами UAC это должно давать правильный вывод. Есть идеи, почему результат неверен?
Это неопределенное поведение, чтобы умножить минимальное значение дополнения со знаком 2 int
на -1, потому что результат находится за пределами диапазона типа.
В этом случае ваш вывод соответствует результату -2147483648, т. Е. Переполнение, похоже, обернулось вокруг. Вы не можете полагаться на перенос для подписанных типов, только для неподписанных типов.
Присвоение результата расчета unsigned long long
не меняет тип, в котором выполняется вычисление. Как только вы сделаете умножение, вы проиграете. Итак, преобразовать один из операндов в unsigned long long
до множатся.
Оба операнда int
, поэтому арифметика выполняется в пределах int
тип; результат операции выходит за пределы диапазона int
, так что результат не определен.
Чтобы получить ожидаемый результат, приведите один операнд к long long
первый:
unsigned long long result = left * (long long) right;
Это все еще потенциально неопределенное поведение; безопаснее преобразовать в беззнаковую арифметику как можно раньше (поскольку арифметика без знака переносится и не переполняется):
unsigned long long result = left * (unsigned long long) right;
Обратите внимание, что результат, к которому вы пришли, 0xffffffff80000000
; это указывает на то, что фактический результат операции был std::numeric_limits<int>::min()
в int
тип, который затем был расширен знак и приведен к unsigned long long
,
Причина в том, что умножение совершается с точки зрения int
,
Оба аргумента int
, так что умножение дает int
Agein, и вы были правы, это дает int_max
+1, что эквивалентно int_min
= -2147483648. Так что на самом деле это -2147483648, но для длинных без знака он эквивалентен 18446744071562067968, см. Шестнадцатеричные коды:
int_min = 80000000
(unsigned long long) (int min) = ffffffff80000000