Вы попали в ловушку, пытаясь использовать результат, чтобы проверить, произошло ли переполнение. На самом деле вы не можете этого сделать. Подписанное целочисленное переполнение имеет неопределенное поведение, поэтому, как только это произошло, вы уже ввернуты. Вы должны проверить overlow с помощью операндов, до операции.
Пусть max
- максимально представимое целое число. Предполагая, что операнды положительны, a * b
переполняется тогда и только тогда, когда a * b > max
. Но вы не можете выполнить этот тест, потому что, если переполняется a * b
, результат неприменим. Кроме того, мы знаем, что целое число больше max
, поэтому тест всегда будет ложным.
Итак, как мы можем использовать уравнение, не используя результат a * b
? Мы будем использовать магию математики, и мы получим эквивалентное уравнение: a > max/b
. Мы используем только целочисленный оператор деления, который не переполняется, Nice! Теперь эквивалентность уравнений выполняется только тогда, когда b != 0
. Попытка разделить max/0
будет ошибкой. Но мы знаем, что a * 0
не переполняется ни для каких a
, так что мы можем тривиально реализовать этот частный случай.
Итак, что мы имеем:
int a, b;
// don't forget to initialize
if(b && a > INT_MAX/b)
// overflow, abort!
else
// no overflow, proceed
Это работает правильно только для положительных входов. Я оставлю его как упражнение для чтения, чтобы реализовать тест для всех целых чисел.
Что вы сделали до сих пор? Из-за формулировки ваше задание кажется хитростью. Даже если вы проверяете переполнение * после * операции, вы не можете использовать результат, чтобы проверить его. Вы можете проверить это только с помощью операндов. – user2079303
Не публикуйте код в комментариях. Поместите свой код в свой вопрос. Также описывайте, как ведет себя ваш код и как вы ожидаете, что он будет себя вести. – user2079303
Не имеет значения, где я проверяю переполнение, если результат хорош –