unsignedと2の補数の関係とは?-1が全ビット1になる理由をわかりやすく解説

C言語関連

プログラミングで整数のビット表現を扱っていると、「unsignedなのに-1が全ビット1になるのはなぜか」「それはsignedの考え方ではないのか」といった疑問にぶつかることがあります。この記事では、2の補数表現とunsigned型の関係を整理しながら、この混乱がどこから生まれるのかを解説します。

2の補数表現と「-1」のビット表現

まず前提として、ほとんどの現代コンピュータでは負の整数は2の補数で表現されます。

2の補数では、-1はビットをすべて反転して1を足すことで表され、その結果「すべて1のビット列」になります。

例えば32bit整数では、-1は 0xFFFFFFFF となります。

ここで重要なのは、このビット列自体は「型に依存しないただのパターン」であるという点です。

signedとunsignedで同じビット列がどう解釈されるか

同じビット列でも、signedかunsignedかによって意味は変わります。

signedとして解釈すれば 0xFFFFFFFF は -1 になります。

一方unsignedとして解釈すれば 0xFFFFFFFF は 4294967295 になります。

つまり「ビット列は同じで、解釈だけが違う」というのが本質です。

「unsignedなのに-1が使われているように見える」理由

疑問のポイントはここで、-1という“値”がunsignedに入っているわけではありません。

実際には、-1という値が一度2の補数としてビット列に変換され、その後unsignedとして再解釈されています。

そのため内部的には「負の値をunsignedで扱っている」のではなく、「ビット列をunsignedとして読み直している」だけです。

a-bの計算で起きていること

unsigned型で a – b を行う場合、CPU内部では剰余演算(mod 2^n)として処理されます。

例えば a=0, b=1 の場合、本来の結果は -1 ですが、unsignedでは表現できないため 2^32 – 1 に変換されます。

その結果、0xFFFFFFFF となり、これが4294967295として解釈されます。

これはエラーではなく、規格上の正しい動作です。

signedとunsignedの混同が生む誤解

今回の疑問の本質は「値」と「ビット列」と「型の解釈」を混同している点にあります。

2の補数はsignedのための仕組みですが、生成されたビット列は型に依存せず再解釈可能です。

そのためunsignedでも同じビット列を扱うこと自体は問題ではありません。

まとめ

2の補数で得られるビット列はsigned専用のものではなく、単なるビットパターンとして扱われます。

そのビット列をunsignedとして解釈すれば大きな正の数になり、signedとして解釈すれば負の数になります。

重要なのは「値そのもの」ではなく「どう解釈するか」という点です。

コメント

タイトルとURLをコピーしました