符号付き整数と符号なし整数の違いは何ですか?
おそらくご存じのとおり、int
sは内部的にバイナリで保存されます。通常、int
には32ビットが含まれますが、環境によっては16ビットまたは64ビット(または異なる数、通常は2の累乗である必要はありません)が含まれる場合があります。
しかし、この例では、4ビット整数を見てみましょう。小さいですが、説明のために役立ちます。
このような整数には4ビットがあるため、16個の値のいずれかを想定できます。 16は2の4乗、または2倍2倍2倍です。それらの値は何ですか?答えは、この整数がsigned int
であるかunsigned int
であるかによって異なります。 unsigned int
を使用すると、値が負になることはありません。値に関連付けられた記号はありません。 4ビットunsigned int
の16の可能な値は次のとおりです。
bits value
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10
1011 11
1100 12
1101 13
1110 14
1111 15
...および4ビットsigned int
の16の可能な値は次のとおりです。
bits value
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 -8
1001 -7
1010 -6
1011 -5
1100 -4
1101 -3
1110 -2
1111 -1
ご覧のとおり、signed int
sの場合、数値が負の場合にのみ、最上位ビットは1
です。 signed int
sの場合、このビットは「符号ビット」として知られている理由です。
int
とunsigned int
は2つの異なる整数型です。 (int
はsigned int
とも呼ばれるか、単にsigned
; unsigned int
はunsigned
とも呼ばれます。)
名前が示すように、int
はsigned整数型であり、unsigned int
はunsigned整数型。つまり、int
は負の値を表すことができ、unsigned int
は負でない値のみを表すことができます。
C言語は、これらの型の範囲にいくつかの要件を課しています。 int
の範囲は少なくとも-32767
.. +32767
でなければならず、unsigned int
の範囲は少なくとも0
.. 65535
でなければなりません。これは、両方のタイプが少なくとも16ビットでなければならないことを意味します。多くのシステムでは32ビット、一部のシステムでは64ビットです。 int
は通常、ほとんどの最新システムで使用される2の補数表現のために、余分な負の値を持ちます。
おそらく最も重要な違いは、符号付き演算と符号なし演算の動作です。符号付きint
の場合、オーバーフローには未定義の動作があります。 unsigned int
の場合、オーバーフローはありません。型の範囲外の値を生成する操作はラップアラウンドします。たとえば、UINT_MAX + 1U == 0U
。
符号付きまたは符号なしの整数型は、数学的な整数の無限集合の部分範囲をモデル化します。型の範囲内の値を操作している限り、すべてが機能します。型の下限または上限に近づくと、不連続が発生し、予期しない結果が生じる可能性があります。符号付き整数型の場合、問題は、INT_MIN
およびINT_MAX
を超える非常に大きな負および正の値でのみ発生します。符号なし整数型の場合、非常に大きな正の値およびゼロで問題が発生します。これはバグの原因になる可能性があります。たとえば、これは無限ループです。
for (unsigned int i = 10; i >= 0; i --) [
printf("%u\n", i);
}
i
はalwaysがゼロ以上であるためです。それが符号なしの型の性質です。 (ループ内で、i
がゼロの場合、i--
はその値をUINT_MAX
に設定します。)
特定の整数変数に格納されている値が常に正であることが事前にわかっている場合があります。たとえば、値を数えるためだけに使用される場合です。このような場合、unsigned int num student;
のように、変数を符号なしとして宣言できます。このような宣言により、許容される整数値の範囲(32ビットコンパイラの場合)は、-2147483648〜+2147483647の範囲から0〜4294967295の範囲にシフトします。したがって、整数を符号なしとして宣言すると、可能な最大サイズそれ以外の場合に保持できる値。
素人の用語では、符号なし整数は負にならない整数であるため、想定できる正の値の範囲が広くなります。符号付き整数は、負の値をとることができますが、負の値を引き換えに負の値をとることができる整数です。
実際には、2つの違いがあります。
cout
またはCのprintf
を使用):符号なし整数ビット表現は、印刷関数によって非負の整数として解釈されます。このコードは、順序付け基準を使用して整数を識別できます。
char a = 0;
a--;
if (0 < a)
printf("unsigned");
else
printf("signed");