web-dev-qa-db-ja.com

符号なしint 0xFFFFFFFFがint -1と等しいのはなぜですか?

CまたはC++では、size_t(unsigned intデータ型)が保持できる最大数は、そのデータ型に-1をキャストすることと同じであると言われています。たとえば、 size_tの無効な値 を参照してください

どうして?

つまり、(32ビット整数について)最上位ビットは符号付きデータ型の符号を保持しています(つまり、ビット0x80000000は負の数を形成します)。 1は0x00000001です。0x7FFFFFFFFは、intデータ型が保持できる最大の正数です。

その後、-1 intのバイナリ表現は0x80000001である必要があります(おそらく私は間違っています)。 intをunsignedにキャストするときに、このバイナリ値が完全に異なるもの(0xFFFFFFFF)に変換される理由/方法または.. 0xFFFFFFFFからバイナリ-1を形成する方法はありますか?

Cでは、((unsigned int)-1)== 0xFFFFFFFFまたは((int)0xFFFFFFFF)== -1が1 + 1 == 2と同等に真であることは間違いありません。なぜだろうと思っています。

26
conejoroy

CおよびC++は、さまざまなアーキテクチャおよびマシンタイプで実行できます。その結果、2の補数と1の補数が最も一般的な数字の異なる表現を持つことができます。一般に、プログラムの特定の表現に依存しないでください。

符号なし整数型(size_tはそのうちの1つ)については、C標準(およびC++標準も同様)が正確なオーバーフロールールを指定しています。つまり、SIZE_MAXsize_t型の最大値である場合、式

(size_t) (SIZE_MAX + 1)

0であることが保証されているため、(size_t) -1SIZE_MAXと等しいことを確認できます。同じことが他の符号なしの型にも当てはまります。

上記が当てはまることに注意してください。

  • すべての符号なし型について、
  • 基礎となるマシンが2の補数の数値を表さない場合でも。この場合、コンパイラーはIDが正しいことを確認する必要があります。

また、上記は、signedタイプの特定の表現に依存できないことを意味します。

編集:コメントのいくつかに答えるために:

次のようなコードスニペットがあるとします。

int i = -1;
long j = i;

jへの割り当てに型変換があります。 intlongのサイズが異なると仮定すると(ほとんどの[すべて?] 64ビットシステム)、ijのメモリ位置のビットパターンは、サイズが異なるため異なることになります。コンパイラーは、iおよびjvalues-1であることを確認します。

同様に、次の場合:

size_t s = (size_t) -1

型変換が行われています。 -1int型です。ビットパターンがありますが、キャストによってsize_tへの変換が行われると、コンパイラーはvalueを規則に従って変換するため、この例には関係ありません。タイプ(この場合はsize_t)。したがって、intsize_tのサイズが異なる場合でも、標準では、上記のsに格納されている値がsize_tが取り得る最大値になることが保証されています。

行う場合:

long j = LONG_MAX;
int i = j;

LONG_MAXINT_MAXより大きい場合、iの値は実装定義です(C89、セクション3.2.1.2)。

47
Alok Singhal

2の補数と呼ばれます。負の数を作成するには、すべてのビットを反転してから1を追加します。1を-1に変換するには0xFFFFFFFEに反転し、1を追加して0xFFFFFFFFにします。

なぜこのように行われたのか、 Wikipedia は言います:

2の補数システムには、加算回路と減算回路がオペランドの符号を調べて、加算するか減算するかを決定する必要がないという利点があります。このプロパティにより、システムの実装がより簡単になり、高精度の算術演算を簡単に処理できるようになります。

26
Mark Ransom

最初の質問、理由(unsigned)-1は、誤って2の補数にのみ関係する符号なしの最大値を与えます。 -1が符号なしの型にキャストされる理由は、その型で可能な最大の値を与えるためです。これは、規格が符号なしの型を「2を法とする算術の法則に従う」と述べているためですn nは、特定のサイズの整数の値表現のビット数です。」

現在、2の補数の場合、可能な限り最大の符号なしの値と-1の表現は同じですが、ハードウェアが別の表現(1の補数または符号/大きさなど)を使用している場合でも、-1を符号なしの型に変換する必要がありますそのタイプに対して可能な限り最大の値を生成します。

7
Jerry Coffin

2の補数 は、加算と同様に減算を行うのに非常に便利です:)

 11111110(254または-2)
 +00000001(1)
 --------- 
 11111111(255または-1)
 
 11111111(255または-1)
 +00000001(1)
 --------- 
 100000000(0 + 256) 
3
pmg

2の補数 エンコーディングです。

主なボーナスは、unsigned intを使用していても、signed intを使用していても同じエンコーディングを取得できることです。 0から1を引くと、整数は単純にラップアラウンドします。したがって、0より小さい1は0xFFFFFFFFです。

1
Goz