2012-06-28 4 views
19

Результат абс (-2147483648) -2147483648, не так ли? кажется неприемлемым.Почему абсолютное значение максимального отрицательного целого числа -2147483648 равно -2147483648?

printf("abs(-2147483648): %d\n", abs(-2147483648)); 

выход:

abs(-2147483648): -2147483648 
+1

Я считаю, что это неопределенное поведение. У меня нет стандартного C, поэтому я не могу его поддержать. –

+5

Что вы ожидаете от этого, учитывая, что 'abs (int)' возвращает 'int'? –

+7

Последний проект C11 говорит (7.21.6.1, about abs и friends) «Если результат не может быть представлен, поведение не определено» –

ответ

18

стандарт говорит о abs():

В abs, labs и llabs функции вычисления абсолютное значение целого числа j. Если результат не может быть представлен, поведение не определено.

И результат действительно не может быть представлен, потому что представление комплемента 2 целых чисел со знаком не является симметричным. Подумайте об этом ... Если у вас есть 32 бита в int, это дает вам 2 отличные значения от INT_MIN до INT_MAX. Это четное число значений. Таким образом, если есть только один 0, число значений больше 0 не может быть таким же, как число значений меньше 0. И поэтому нет положительного аналога INT_MIN со значением - INT_MIN.

Итак, что неприемлемо, вызывает abs(INT_MIN) на вашей платформе.

-5

Попробуйте

printf("abs(-2147483648): %u\n", abs(-2147483648)); 
+5

Это, мой друг, имеет неопределенное поведение. Вы печатаете целое число со знаком с неподписанным форматированием. I -1, потому что он, кроме того, не отвечает на вопрос. –

10

Поскольку 2147483648 больше INT_MAX на вашей реализации, то abs(-2147483648) не определен.

5

Это код в abs.c в исходном коде GNU glibc.

/* Return the absolute value of I. */ 
int 
DEFUN(abs, (i), int i) 
{ 
    return(i < 0 ? -i : i); 
} 

Таким образом, abs (-2147483648) возвращение - (- 2147483648). В x86, это реализовать с помощью этой инструкции два

movl $-2147483648, %eax 
negl %eax 

инструкция negl реализуется таким путем: Num = 0-Num; sbb реализуется следующим образом: Вычитает источник из пункта назначения и вычитает 1 дополнительный, если установлен флаг переноса. Таким образом, abs (-2147483648) (hex - 0x80000000) -> - (- 2147483648) -> 0 - (- 2147483648) становится (0x80000000) окончательно.

детали инструкции negl, пожалуйста визит http://zsmith.co/intel_n.html#neg

детали инструкции SBB, пожалуйста, посетите http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html

+0

И? Я имею в виду, уточните это? –

9

Отрицательные числа обычно представлены белым двоичным дополнением.

Для преобразования положительного на отрицательный он используется логика

x -> not(x)+1 

Для 8 бит арифметическим

01111111b составляет 127 и -127 становится
10000000b + 1 = 10000001b

и обратном направлении -127 10000001b становится
01111110b + 1 = 01111111b

Как насчет -128?

-128 - 10000000b, и нет никакого положительного его аналога, потому что нет 128 в 8 бит арифметики.

10000000 -> 01111111 + 1 = 10000000 и -128 снова

То же относится и к первоначальному вопросу

+0

Вот почему 0 и минимальное значение всегда одинаковы после отрицания в дополнении –