Знаковое целочисленное переполнение похоже на деление на ноль - оно приводит к неопределенному поведению, поэтому вы должны проверить, произойдет ли это перед выполнением операции с потенциально переполнением. Как только вы переполнились, все ставки отключены - ваш код может делать все, что угодно.
Для этого пригодятся макросы *_MAX
и _MIN
, определенные в <limits.h>
, но вы должны быть осторожны, чтобы не вызвать неопределенное поведение в самих тестах. Например, чтобы проверить, не переполнится ли a * b
данный int a, b;
, вы можете использовать:
if ((b > 0 && a <= INT_MAX / b && a >= INT_MIN / b) ||
(b == 0) ||
(b == -1 && a >= -INT_MAX) ||
(b < -1 && a >= INT_MAX / b && a <= INT_MIN / b))
{
result = a * b;
}
else
{
/* calculation would overflow */
}
(Обратите внимание, что при этом избегается одна тонкая ловушка, заключающаяся в том, что вы не можете вычислить INT_MIN / -1
- такое число не гарантировано представимо и действительно вызывает фатальную ловушку на обычных платформах).
person
caf
schedule
07.10.2011