我使用的是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位字符。
比特没有任何"绝对"意义。它们可以表示任何东西,这取决于你如何"看待"它们(它们具有哪种类型)。
~
运算符对其实参执行1 -补码操作,无论实参是有符号整数还是无符号整数都无关紧要。它只是翻转所有的位,所以
0000 0000 0000 1010 (bin) / 10 (dec)
是
1111 1111 1111 0101 (bin)
(这里,假定这些数字是32位宽——我省略了16个0和1)
cout
如何显示结果?它看的是原始类型。对于有符号整数,最高位是它的符号。因此,结果总是负(因为10
中的最高有效位是0
)。要将一个负数显示为一个正数,您需要这两个数的补码:将所有位取倒数,然后加1。例如,-1
,二进制111..111
,显示为(反转)000..000
然后+1:000..001
。结果:-1
.
将此应用于10
的一补,您将得到111..110101
->逆变化成000...001010
,然后添加1
。结果:-11。
对于无符号数,cout
不会这样做(自然),因此您得到一个较大的数字:最大可能的整数减去原始数字。
在内存中,两种情况下都存储为4294967285(4294967296正确地说是拼写错误,33位?),这个数字的含义取决于您使用的签名:
- 如果有符号,这个数字是-11。
- 如果是无符号,则为4294967285
同一个数字的不同解释
您可以通过强制转换将其重新解释为unsigned,结果相同:
int a = 10;
cout << (unsigned int) ~a << endl;
试试这个
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;
}