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と同等に真であることは間違いありません。なぜだろうと思っています。
CおよびC++は、さまざまなアーキテクチャおよびマシンタイプで実行できます。その結果、2の補数と1の補数が最も一般的な数字の異なる表現を持つことができます。一般に、プログラムの特定の表現に依存しないでください。
符号なし整数型(size_t
はそのうちの1つ)については、C標準(およびC++標準も同様)が正確なオーバーフロールールを指定しています。つまり、SIZE_MAX
がsize_t
型の最大値である場合、式
(size_t) (SIZE_MAX + 1)
0
であることが保証されているため、(size_t) -1
がSIZE_MAX
と等しいことを確認できます。同じことが他の符号なしの型にも当てはまります。
上記が当てはまることに注意してください。
また、上記は、signedタイプの特定の表現に依存できないことを意味します。
編集:コメントのいくつかに答えるために:
次のようなコードスニペットがあるとします。
int i = -1;
long j = i;
j
への割り当てに型変換があります。 int
とlong
のサイズが異なると仮定すると(ほとんどの[すべて?] 64ビットシステム)、i
とj
のメモリ位置のビットパターンは、サイズが異なるため異なることになります。コンパイラーは、i
およびj
のvaluesが-1
であることを確認します。
同様に、次の場合:
size_t s = (size_t) -1
型変換が行われています。 -1
はint
型です。ビットパターンがありますが、キャストによってsize_t
への変換が行われると、コンパイラーはvalueを規則に従って変換するため、この例には関係ありません。タイプ(この場合はsize_t
)。したがって、int
とsize_t
のサイズが異なる場合でも、標準では、上記のs
に格納されている値がsize_t
が取り得る最大値になることが保証されています。
行う場合:
long j = LONG_MAX;
int i = j;
LONG_MAX
がINT_MAX
より大きい場合、i
の値は実装定義です(C89、セクション3.2.1.2)。
2の補数と呼ばれます。負の数を作成するには、すべてのビットを反転してから1を追加します。1を-1に変換するには0xFFFFFFFEに反転し、1を追加して0xFFFFFFFFにします。
なぜこのように行われたのか、 Wikipedia は言います:
2の補数システムには、加算回路と減算回路がオペランドの符号を調べて、加算するか減算するかを決定する必要がないという利点があります。このプロパティにより、システムの実装がより簡単になり、高精度の算術演算を簡単に処理できるようになります。
最初の質問、理由(unsigned)-1
は、誤って2の補数にのみ関係する符号なしの最大値を与えます。 -1が符号なしの型にキャストされる理由は、その型で可能な最大の値を与えるためです。これは、規格が符号なしの型を「2を法とする算術の法則に従う」と述べているためですn nは、特定のサイズの整数の値表現のビット数です。」
現在、2の補数の場合、可能な限り最大の符号なしの値と-1の表現は同じですが、ハードウェアが別の表現(1の補数または符号/大きさなど)を使用している場合でも、-1を符号なしの型に変換する必要がありますそのタイプに対して可能な限り最大の値を生成します。
2の補数 は、加算と同様に減算を行うのに非常に便利です:)
11111110(254または-2) +00000001(1) --------- 11111111(255または-1) 11111111(255または-1) +00000001(1) --------- 100000000(0 + 256)
2の補数 エンコーディングです。
主なボーナスは、unsigned intを使用していても、signed intを使用していても同じエンコーディングを取得できることです。 0から1を引くと、整数は単純にラップアラウンドします。したがって、0より小さい1は0xFFFFFFFFです。