12

我正在使用 Visual Studio 2013。
最近我尝试了~1 的补码运算符:

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

输出是-11

但对于

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

输出是4294967296

我不明白为什么输出是-11有符号的int。请帮我解决这个困惑。

4

4 回答 4

22

当您将数字 10 放入 32 位有符号或无符号整数时,您会得到

0000 0000  0000 0000  0000 0000  0000 1010

当你否定它时,你得到

1111 1111  1111 1111  1111 1111  1111 0101

这 32 位表示 4294967285 作为无符号整数,或 -11 作为有符号整数(您的计算机将负整数表示为二进制补码)。它们也可以表示一个 32 位浮点数或四个 8 位字符。

位没有任何“绝对”含义。它们可以代表任何东西,这取决于您如何“看待”它们(它们具有哪种类型)。

于 2014-06-01T11:27:41.670 回答
4

运算符对其参数~执行补码,参数是有符号整数还是无符号整数都没有关系。它只是翻转所有位,所以

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

变成

1111 1111 1111 0101 (bin)

(据推测,这些数字是 32 位宽——我又省略了 16 个 0 和 1。)

将如何cout显示结果?它着眼于原始类型。对于有符号整数,最高有效位是它的符号。因此,结果总是负数(因为最重要的位100)。要将负数显示为正数,您需要二进制补码:反转所有位,然后加 1。例如,-1, binary 111..111,显示为 (inverting)000..000然后 +1: 000..001。结果:-1

将此应用于10您的补码111..110101-> 反转为000...001010,然后添加1。结果:-11。

对于无符号数,cout(自然)不会这样做,因此您会得到一个大数:可能的最大整数减去原始数。

于 2014-06-01T11:33:14.120 回答
2

在内存中,两种情况下都存储了 4294967285(4294967296 是错字,33 位?),这个数字的含义取决于您使用的符号:

  • 如果已签名,则该数字为-11。
  • 如果未签名,则为 4294967285

同一个数字的不同解释。

您可以通过强制转换将其重新解释为无符号,结果相同:

int a = 10;
cout << (unsigned int) ~a << endl;
于 2014-06-01T11:30:21.310 回答
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;
}
于 2015-08-27T14:51:17.997 回答