[英]Why the absolute value of the max negative integer -2147483648 is still -2147483648?
abs(-2147483648) 的結果是-2147483648,不是嗎? 這似乎是不可接受的。
printf("abs(-2147483648): %d\n", abs(-2147483648));
輸出:
abs(-2147483648): -2147483648
標准說的是abs()
:
abs
、labs
和llabs
函數計算整數j
的絕對值。 如果結果無法表示,則行為未定義。
結果確實無法表示,因為有符號整數的 2 的補碼表示不是對稱的。 想想看......如果你在int
有 32 位,那會給你從INT_MIN
到INT_MAX
2 32 個不同的值。 這是偶數個值。 因此,如果只有一個 0,則大於 0 的值的數量不能與小於 0 的值的數量相同。因此, INT_MIN
的值為 - INT_MIN
沒有正對應。
因此,在您的平台上調用abs(INT_MIN)
是不可接受的。
負數通常用二進制補碼表示。
要將正數轉換為負數,它使用邏輯
x -> not(x)+1
對於 8 位算術
01111111b 是 127 而 -127 變成
10000000b + 1 = 10000001b
和相反的方向 -127 10000001b 變成
01111110b + 1 = 01111111b
-128呢?
-128 是 10000000b 並且沒有它的正對應物,因為在 8 位有符號算術中沒有 128。
10000000 -> 01111111 + 1 = 10000000 和 -128
同樣適用於原始問題
由於 2147483648 在您的實現中大於INT_MAX
,因此abs(-2147483648)
未定義。
這是 GNU glibc 源代碼中 abs.c 中的代碼。
/* 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
試試這個
printf("abs(-2147483648): %u\n", abs(-2147483648));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.