Там (1):
// assume x,y are non-negative
if(x > max - y) error;
И (2):
// assume x,y are non-negative
int sum = x + y;
if(sum < x || sum < y) error;
Какой из них предпочтительнее или есть лучший способ.
Там (1):
// assume x,y are non-negative
if(x > max - y) error;
И (2):
// assume x,y are non-negative
int sum = x + y;
if(sum < x || sum < y) error;
Какой из них предпочтительнее или есть лучший способ.
Целочисленное переполнение является каноническим примером поведения undefined в C (отмечая, что операции с целыми целыми без знака никогда не переполняются, вместо этого они определяются как обход). Это означает, что после того, как вы выполнили x + y
, если он переполнен, вы уже были заняты. Слишком поздно делать какие-либо проверки - ваша программа могла быть разбита. Подумайте, как проверить деление на ноль - если вы подождете, пока после деления не будет выполнено, это уже слишком поздно.
Итак, это означает, что метод (1) - единственный правильный способ сделать это. Для max
вы можете использовать INT_MAX
из <limits.h>
.
Если x
и/или y
может быть отрицательным, тогда все сложнее - вам нужно выполнить тест таким образом, чтобы сам тест не мог вызвать переполнение.
if ((y > 0 && x > INT_MAX - y) ||
(y < 0 && x < INT_MIN - y))
{
/* Oh no, overflow */
}
else
{
sum = x + y;
}
Вы действительно можете проверить только переполнение с unsigned
целыми и арифметическими:
unsigned a,b,c;
a = b + c;
if (a < b) {
/* overflow */
}
Поведение переполнения со знаками целых чисел undefined в C, но на большинстве машин вы можете использовать
int a,b,c;
a = b + c;
if (c < 0 ? a > b : a < b) {
/* overflow */
}
Это не будет работать на машинах, которые используют любую арифметику насыщения
Вам нужно только проверить один из них. Если x + y переполняется, он будет меньше, чем x и y. Следовательно:
int sum = x + y;
if (sum < x) error;
должно быть достаточно.
На следующем сайте есть куча вещей о переполнении целых чисел:
Если вы хотите обрабатывать отрицательные числа, его можно развернуть:
int sum = x + y;
if (y >= 0) {
if (sum < x) error;
} else {
if (sum > x) error;
}