Наименьшее отрицательное значение знакового целочисленного типа не имеет соответствующей положительной величины. В результате вычисления модуля числа от такого значения функциями 'abs', 'labs', 'llabs' возникает переполнение. Это приводит к неопределённому поведению.
Рассмотрим пример:
#include <iostream> #include <cmath> #include <limits.h> int main() { int min = INT_MIN; // error: abs(-2147483648) = -2147483648 std::cout << "abs(" << min << ") = " << abs(min); // <= return 0; }
Минимальное значение 32-битного знакового типа 'int' имеет значение 'INT_MIN', равное -2147483648. При этом максимальное значение 'INT_MAX' равно 2147483647, что на единицу меньше, чем настоящий модуль числа 'INT_MIN'. В данном случае в результате вычисления модуля получилось отрицательное число, равное исходному значению аргумента. Это может привести к ошибке в пограничном случае, когда код не рассчитан на обработку отрицательных чисел, полученных после вычисления модуля числа.
Для остальных значений функция вычисления модуля будет вести себя ожидаемым образом:
int main() { int notQuiteMin = INT_MIN + 1; // ok: abs(-2147483647) = 2147483647 std::cout << "abs(" << notQuiteMin << ") = " << abs(notQuiteMin); return 0; }
Возможно, перед расчётом модуля стоит сделать специальную проверку значения аргумента, чтобы не допустить возникновения пограничного случая:
void safe_abs_call(int value) { if (value == INT_MIN) return; std::cout << "abs(" << value << ") = " << abs(value); }
Срабатывание диагностики можно подавить в случаях, если де-факто диапазон передаваемых функциям 'abs', 'labs' и 'llabs' значений не может достигать минимальной величины.
Данная диагностика классифицируется как:
|