web-dev-qa-db-ja.com

C / C ++で〜を使用した1の補数

Visual Studio 2013を使用しています。
最近、1の補数で~演算子を試しました:

int a = 10;
cout << ~a << endl;

出力は-11です

しかし

unsigned int a = 10;
cout << ~a << endl;

出力は4294967296です

署名されたintの場合、出力が-11になる理由がわかりません。この混乱を助けてください。

7
user2912611

数値10を32ビットの符号付きまたは符号なし整数に入れると、

0000 0000  0000 0000  0000 0000  0000 1010

否定すると、

1111 1111  1111 1111  1111 1111  1111 0101

これらの32ビットは、符号なし整数として4294967285、または符号付き整数として-11を意味します(コンピューターは負の整数を 2の補数 として表します)。また、32ビット浮動小数点数または4つの8ビット文字を意味する場合もあります。

ビットには「絶対的な」意味はありません。それらは、それらをどのように「見る」か(どのタイプであるか)に応じて、何でも表すことができます。

16
Ivan Kuckir

~演算子は、引数に対して ones-complement を実行します。引数が符号付き整数か符号なし整数かは関係ありません。すべてのビットを反転するだけなので、

0000 0000 0000 1010 (bin) / 10 (dec)

なる

1111 1111 1111 0101 (bin)

(おそらく、これらの数値は32ビット幅です-私はさらに16個の0と1を省略しました。)

coutはどのように結果を表示しますか?元のタイプを見ます。 signed整数の場合、最上位ビットはその符号です。したがって、結果は常にnegativeになります(10の最上位ビットは0であるため)。負の数を正の数として表示するには、2の補数が必要です。つまり、すべてのビットを反転してから1を加算します。たとえば、-1、バイナリ111..111000..000と表示次に+1:000..001。結果:-1

これを10の補数に適用すると、111..110101-> 000...001010に反転し、1が追加されます。結果:-11。

unsigned数の場合、coutはこれを(自然に)実行しないため、大きな数、つまり可能な最大の整数を取得しますminus元の数値。

4
usr2564301

これを試して

unsigned int getOnesComplement(unsigned int number){

unsigned onesComplement = 1;
if(number < 1)
    return onesComplement;
size_t size = (sizeof(unsigned int) * 8 - 1) ;
unsigned int oneShiftedToMSB = 1 << size;

unsigned int shiftedNumber = number;
for ( size_t bitsToBeShifted = 0; bitsToBeShifted < size; bitsToBeShifted++){
    shiftedNumber = number << bitsToBeShifted;
    if(shiftedNumber & oneShiftedToMSB){
        onesComplement = ~shiftedNumber;
        onesComplement = onesComplement >> bitsToBeShifted;
        break;
    }
}
return onesComplement;
}
1
Agnit

メモリには、どちらの場合も4294967285(4294967296はタイプミス、33ビットですか?)が格納されています。この数値の意味は、使用する符号によって異なります。

  • 署名されている場合、これは-11です。
  • 署名されていない場合は4294967285

同じ数の異なる解釈。

キャストすることで、署名なしとして再解釈できます。同じ結果です。

int a = 10;
cout << (unsigned int) ~a << endl;
1
user1129665