我正在使用Visual Studio 2013.
最近我尝试了~
运算符1的补码:
int a = 10;
cout << ~a << endl;
输出为-11
但是
unsigned int a = 10;
cout << ~a << endl;
输出为4294967296
在签名-11
的情况下,我不明白为什么输出为int
。
请帮我解决这个困惑。
答案 0 :(得分:16)
当你将数字10放入32位有符号或无符号整数时,你得到
0000 0000 0000 0000 0000 0000 0000 1010
当你否定它时,你会得到
1111 1111 1111 1111 1111 1111 1111 0101
这32位表示4294967285为无符号整数,或-11为有符号整数(您的计算机表示负整数为Two's complement)。它们还可以表示32位浮点数或4个8位字符。
比特没有任何“绝对”含义。它们可以代表任何东西,具体取决于你“看”它们的方式(它们具有哪种类型)。
答案 1 :(得分:4)
~
运算符对其参数执行ones-complement,无论参数是有符号整数还是无符号整数都无关紧要。它只是翻转所有位,所以
0000 0000 0000 1010 (bin) / 10 (dec)
变为
1111 1111 1111 0101 (bin)
(其中,据推测,这些数字是32位宽 - 我省略了16个0和1。)
cout
将如何显示结果?它查看原始类型。对于 signed 整数,最重要的位是其符号。因此,结果始终是否定(因为10
中最重要的位是0
)。要将负数显示为正数,需要二进制补码:反转所有位,然后加1.例如,-1
,二进制111..111
,显示为(反转)000..000
然后+1:000..001
。结果:-1
。
将此应用于10
的{{1}}的补码,您得到111..110101
- &gt;反转为000...001010
,然后添加1
。结果:-11。
对于无符号号码,cout
不会(自然地)执行此操作,因此您得到一个大数字:最大可能的整数减去原始号码。
答案 2 :(得分:1)
在内存中,两种情况下都存储了4294967285(4294967296正确是一个错字,33位?),这个数字的含义取决于你使用的标记:
对相同数字的不同解释。
您可以通过强制转换将其重新解释为无符号,结果相同:
int a = 10;
cout << (unsigned int) ~a << endl;
答案 3 :(得分:1)
试试这个
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;
}