在 C/C++ 中使用 ~ 的 1 补码



我使用的是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;
}

相关内容

  • 没有找到相关文章

最新更新