Visual Studio 2013を使用しています。
最近、1の補数で~
演算子を試しました:
int a = 10;
cout << ~a << endl;
出力は-11
です
しかし
unsigned int a = 10;
cout << ~a << endl;
出力は4294967296
です
署名されたint
の場合、出力が-11
になる理由がわかりません。この混乱を助けてください。
数値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ビット文字を意味する場合もあります。
ビットには「絶対的な」意味はありません。それらは、それらをどのように「見る」か(どのタイプであるか)に応じて、何でも表すことができます。
~
演算子は、引数に対して 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..111
、000..000
と表示次に+1:000..001
。結果:-1
。
これを10
の補数に適用すると、111..110101
-> 000...001010
に反転し、1
が追加されます。結果:-11。
unsigned数の場合、cout
はこれを(自然に)実行しないため、大きな数、つまり可能な最大の整数を取得しますminus元の数値。
これを試して
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;
}
メモリには、どちらの場合も4294967285(4294967296はタイプミス、33ビットですか?)が格納されています。この数値の意味は、使用する符号によって異なります。
同じ数の異なる解釈。
キャストすることで、署名なしとして再解釈できます。同じ結果です。
int a = 10;
cout << (unsigned int) ~a << endl;