web-dev-qa-db-ja.com

符号付き整数と符号なし整数の違いは何ですか

符号付き整数と符号なし整数の違いは何ですか?

66
Moumita Das

おそらくご存じのとおり、intsは内部的にバイナリで保存されます。通常、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 intsの場合、数値が負の場合にのみ、最上位ビットは1です。 signed intsの場合、このビットは「符号ビット」として知られている理由です。

intunsigned intは2つの異なる整数型です。 (intsigned intとも呼ばれるか、単にsigned; unsigned intunsignedとも呼ばれます。)

名前が示すように、intsigned整数型であり、unsigned intunsigned整数型。つまり、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);
}

ialwaysがゼロ以上であるためです。それが符号なしの型の性質です。 (ループ内で、iがゼロの場合、i--はその値をUINT_MAXに設定します。)

13
Keith Thompson

特定の整数変数に格納されている値が常に正であることが事前にわかっている場合があります。たとえば、値を数えるためだけに使用される場合です。このような場合、unsigned int num student;のように、変数を符号なしとして宣言できます。このような宣言により、許容される整数値の範囲(32ビットコンパイラの場合)は、-2147483648〜+2147483647の範囲から0〜4294967295の範囲にシフトします。したがって、整数を符号なしとして宣言すると、可能な最大サイズそれ以外の場合に保持できる値。

10
imran

素人の用語では、符号なし整数は負にならない整数であるため、想定できる正の値の範囲が広くなります。符号付き整数は、負の値をとることができますが、負の値を引き換えに負の値をとることができる整数です。

8
user2977636

実際には、2つの違いがあります。

  1. 印刷(例:C++のcoutまたはCのprintfを使用):符号なし整数ビット表現は、印刷関数によって非負の整数として解釈されます。
  2. ordering:順序は、符号付きまたは符号なしの仕様に依存します。

このコードは、順序付け基準を使用して整数を識別できます。

char a = 0;
a--;
if (0 < a)
    printf("unsigned");
else
    printf("signed");
1
nano