Abs(-2147483648)の結果は-2147483648ですよね?それは受け入れられないようです。
printf("abs(-2147483648): %d\n", abs(-2147483648));
出力:
abs(-2147483648): -2147483648
標準では、abs()
について次のように述べています。
abs
、labs
、およびllabs
関数は、整数j
の絶対値を計算します。結果を表現できない場合、動作は定義されていません。
また、符号付き整数の2の補数表現は対称ではないため、結果を実際に表すことはできません。考えてみてください...int
に32ビットがある場合、2が得られます32 _INT_MIN
_から_INT_MAX
_までの個別の値。これは偶数の値です。したがって、0が1つしかない場合、0より大きい値の数を0より小さい値の数と同じにすることはできません。したがって、値が-_INT_MIN
_の_INT_MIN
_に正の対応物はありません。 。
したがって、受け入れられないのは、プラットフォームでabs(INT_MIN)
を呼び出すことです。
負の数は通常、2進数の補数で表されます。
正から負に変換するには、ロジックが使用されます
x -> not(x)+1
8ビット演算の場合
01111111bは127で、-127は
10000000b + 1 = 10000001b
反対方向に-12710000001bは
01111110b + 1 = 01111111b
-128はどうですか?
-128は10000000bであり、8ビットの符号付き演算に128がないため、正の対応物はありません。
10000000-> 01111111 + 1 = 10000000および-128再び
同じことが元の質問にも当てはまります
実装では2147483648が_INT_MAX
_より大きいため、abs(-2147483648)
は未定義です。
これは、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では、この2つの命令によって実装されます
movl $-2147483648, %eax
negl %eax
negl命令は、次のように実装されます。num= 0-num; sbbは、次の方法で実装されます。宛先からソースを減算し、キャリーフラグが設定されている場合はさらに1を減算します。したがって、abs(-2147483648)(16進数は0x80000000)->-(-2147483648)-> 0-(-2147483648)は最終的に(0x80000000)になります。
negl命令の詳細については、次のWebサイトをご覧ください---(http://zsmith.co/intel_n.html#neg
sbb命令の詳細については、次のWebサイトをご覧ください http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html