例えば:
unsigned int i = ~0;
結果:割り当て可能な最大数i
と
signed int y = ~0;
結果:-1
なぜ私は得るの-1
ですか?に割り当てることができる最大数を取得するべきではありませんy
か?
例えば:
unsigned int i = ~0;
結果:割り当て可能な最大数i
と
signed int y = ~0;
結果:-1
なぜ私は得るの-1
ですか?に割り当てることができる最大数を取得するべきではありませんy
か?
両方4294967295
(aka UINT_MAX
) と-1
の同じバイナリ表現0xFFFFFFFF
または 32 ビットがすべて に設定されてい1
ます。これは、符号付き数値が2 の補数を使用して表されるためです。負の数の MSB (最上位ビット) は に設定され1
、その値は残りのビットを反転し、 を加算1
して乗算することによって決定され-1
ます。したがって、MSB が に設定され1
、残りのビットも に設定されている1
場合、それらを反転し (32 個のゼロを取得)、加算1
( を取得1
) し、 を乗算し-1
て最終的に を取得し-1
ます。
これにより、CPU は負の数に対して特別な例外を必要としないため、計算が容易になります。たとえば、0xFFFFFFFF
(-1) とを足してみてください1
。32 ビットの余地しかないため、これはオーバーフローし、結果は0
期待どおりになります。
詳細については、次を参照してください。
unsigned int i = ~0;
結果: i に割り当てることができる最大数
通常、必ずしもそうではありません。式は、すべての (非パディング) ビットが設定~0
された として評価されます。int
C 標準では、符号付き整数の 3 つの表現が許可されています。
~0 = -1
を に代入すると、 がunsigned int
得られ(-1) + (UINT_MAX + 1) = UINT_MAX
ます。~0
、負のゼロまたはトラップ表現のいずれかです。負のゼロの場合、への代入unsigned int
は 0 になります。~0
はINT_MIN == -INT_MAX
であり、それを に代入すると、幅 (符号なし整数型のunsigned int
値ビット数 + 1 [符号ビットの場合は値ビット数 + 1]) を持つ可能性(UINT_MAX + 1) - INT_MAX
は1
ほとんどありません。 ] の幅が の幅と同じである一般的なケースでは、のunsigned int
それよりも小さい (符号付き整数型の場合) 。int
2^(WIDTH - 1) + 1
unsigned int
int
初期化
unsigned int i = ~0u;
常にi
値を保持しますUINT_MAX
。
signed int y = ~0;
結果: -1
上で述べたように、符号付き整数の表現が 2 の補数を使用している場合のみです (現在では、これが最も一般的な表現です)。
~0
は、すべてのビットが 1 に設定された単なるです。これをint
解釈するunsigned
と、 と同等になりUINT_MAX
ます。と解釈するsigned
と となります-1
。
32 ビット整数を想定すると、次のようになります。
0 = 0x00000000 = 0 (signed) = 0 (unsigned)
~0 = 0xffffffff = -1 (signed) = UINT_MAX (unsigned)
パウロの答えは絶対に正しいです。〜0を使用する代わりに、次を使用できます。
#include <limits.h>
signed int y = INT_MAX;
unsigned int x = UINT_MAX;
そして今、あなたが値をチェックするならば:
printf("x = %u\ny = %d\n", UINT_MAX, INT_MAX);
システムの最大値を確認できます。
いいえ、~
はビット単位の NOT演算子であり、型演算子の最大値ではないためです。unsigned として解釈されると unsigned で表現可能な最大数が得られ、signed int として解釈されると -1 が得られ~0
ますint
。1
http://en.wikipedia.org/wiki/Two%27s_complementを調べて、ブール代数と論理設計について少し学んでください。また、バイナリでカウントする方法と、バイナリでの足し算と引き算の方法を学習すると、これがさらに説明されます。
C 言語はこの形式の数値を使用したため、最大の数値を見つけるには 0x7FFFFFFF を使用する必要があります。(使用する各バイトに 2 つの FF を使用し、左端のバイトは 7 です。) これを理解するには、16 進数とその動作を調べる必要があります。
次に、符号なしの同等物について説明します。符号付きの数値では、数値の下半分が負になります (0 は正の数値と見なされるため、実際には負の数値は正の数値よりも 1 大きくカウントされます)。符号なしの数値はすべて正です。したがって、理論的には、32ビットintの最大数は2 ^ 32ですが、0はまだ正としてカウントされるため、実際には2 ^ 32-1であり、符号付き数値の半分は負です。これは、前の数値 2^32 を 2 で割ることを意味します。32 は指数であるため、両側に 2^31 の数値が得られます。0 が正であることは、符号付き 32 ビット int の範囲が (-2^31, 2^31- 1)。
範囲を比較するだけです: unsigned 32 bit int: (0, 2^32-1) signed 32 bit int: (-2^31, 2^32-1) unsigned 16 bit int: (0, 2^16-1)符号付き 16 ビット整数: (-2^15, 2^15-1)
ここでパターンを見ることができるはずです。~0 のことを説明するには、もう少し時間がかかります。これは、2 進数での減算に関係しています。1 を足してすべてのビットを反転させてから、2 つの数値を足し合わせるだけです。C は舞台裏でこれを行い、多くのプロセッサ (x86 および x64 のプロセッサ ラインを含む) も同様です。このため、負の数をカウント ダウンのように格納するのが最善であり、2 の補数では加算された 1 も隠されます。 . 0 は正と見なされるため、負の数は 0 の値を持つことができないため、自動的に -1 (ビット反転後の正の 1) が追加されます。負の数をデコードするときは、これを考慮する必要があります。
2 の補数のマシンを使用している必要があります。