Страницы

Поиск по вопросам

пятница, 19 октября 2018 г.

Не работает унарный минус на INT_MIN

Если попытаться применить операцию унарного минуса к числу типа int, содержащее INT_MIN, то ничего не изменяется.
Собственно сабж:
#include #include
int main (void) { int a = INT_MIN;
printf("a = %d
", a); a = -a; printf("a = %d
", a);
return 0; }
Результат работы (компилятор - Clang):
a = -2147483648 a = -2147483648
В чем проблема?
P.S. стандарт c99 никакие ограничения (вроде) не накладывает:
6.5.3.3 Unary arithmetic operators ... The result of the unary - operator is the negative of its (promoted) operand. The integer promotions are performed on the operand, and the result has the promoted type.


Ответ

-INT_MIN значение ведёт к неопределённому поведению (undefined behavior) в Си из-за переполнения (integer overflow). Это не только теоретическая проблема, к примеру
#define abs(x) ((x) > 0 ? (x) : -(x))
int foo(int x){ return abs(x) >= 0; }
может быть скомпилировано в
mov eax, 1 ret
то есть даже для INT_MIN возвращается 1 вне зависимости от того как int представлен, то есть даже на реализациях где дополнительный код используется, где -n может вернуть INT_MIN
Переполнение возникает так как INT_MIN по модулю математически может быть больше INT_MAX
n == -n получается в дополнительном коде, так как унарный минус можно реализовать как: обратить биты, прибавить один: -n == ~n+1. К примеру, для 8-битного числа
n=-128 1000 0000 ~n 0111 1111 ~n+1 1000 0000

Комментариев нет:

Отправить комментарий