2016-07-10 1 views
1

は、私が見たこと-0x80000000 + -0x80000000 = 0これは私には意味がありませんでしたので、私は、迅速なCプログラムは、以下のテストするために、実際の答えは0で書きました:なぜ-0x80000000 + -0x80000000 == 0ですか? programmignトリックについての本を読んでいる間

#include <stdio.h> 

int main() 
{ 
    int x = -0x80000000; 
    int y = -0x80000000; 

    int z = x + y; 

    printf("Z is: %d", z); 
    return 0; 
} 

誰もがなぜ光を当てることができますか?私はオーバーフローについて何かを見ましたが、例外やその他のエラーではなく、オーバーフローが0を引き起こす仕組みはわかりません。私は何の警告も何も得られない。

+1

はい、オーバーフローします。いいえ、Cは通常、整数のオーバーフローに対して警告または例外をスローしません。実際の答えの下位32ビットがすべて0であるため、0が表示されます。整数のオーバーフローが発生すると、モジュロ2^32のモジュロ4294967296を返す傾向があります。 –

答えて

2

符号付き整数の正確な表現が定義されていないため、ここで起こっているのは符号付き整数オーバーフローです。これはundefined behaviorです。

しかし実際には、ほとんどの機械では符号付き整数の2の補数表現を使用していますが、この特定のプログラムがこれを利用します。

0x80000000は、符号なし整数定数です。 -はそれを否定し、式をsignedに変更します。 intがシステム上で32ビットであると仮定すると、この値は依然として適合します。実際、これは符号付き32ビットのintが保持できる最小の値であり、この数値の16進表現は0x80000000になります。

2の補数表現で数値を追加するときに、記号を気にする必要がないという特徴があります。それらは、符号なしの数字とまったく同じ方法で追加されます。

我々はxyを追加するときに、私たちはこの取得:

0x80000000 
+ 0x80000000 
------------- 
    0x100000000 

システム上intが32ビットであるため、唯一の最下位32ビットが保持されます。これらのビットの値は0です。

これは実際には未定義の動作です。これは、あなたのマシンが符号付き整数の2の補数表現を使用し、intが32ビットであるために機能します。これは、ほとんどのマシン/コンパイラでは一般的ですが、すべてではありません。

+1

'0x80000000'の型は実装定義です。署名されている可能性があります。 – 2501

+2

符号なしの型を単に否定しても、符号付きの型は返されません。いくつかの仮定の下では、OPの場合、符号なしの値は(正の)値0x80000000に戻ります。 – 2501

+0

ありがとう、何が起こっているのか理解するのを手伝ってくれました。 – MHartley

1

あなたが見ているのは、多くの実装で定義された動作です。実行時に未定義の動作を引き起こす可能性が非常に高いです。それ以上のことは、あなたと本の作家のアーキテクチャについての詳細なしでは知ることができません。

追加情報なしでは意味がありません。明確な回答が必要な場合は、アーキテクチャのタイプ範囲を調べて、割り当てと算術の結果がそれぞれのタイプに適合することを確認してください。

関連する問題