简体   繁体   English

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

[英]1's complement using ~ in C/C++

I am using Visual Studio 2013. 我正在使用Visual Studio 2013。
Recently I tried the ~ operator for 1's complement: 最近我尝试了~运算符1的补码:

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

Output is -11 输出为-11

But for 但对于

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

the output is 4294967296 输出是4294967296

I don't get why the output is -11 in the case of signed int . 我不明白为什么在signed int的情况下输出是-11 Please help me with this confusion. 请帮我解决这个困惑。

When you put number 10 into 32-bit signed or unsigned integer, you get 当你将数字10放入32位有符号或无符号整数时,你就得到了

0000 0000  0000 0000  0000 0000  0000 1010

When you negate it, you get 当你否定它时,你会得到

1111 1111  1111 1111  1111 1111  1111 0101

These 32 bits mean 4294967285 as an unsigned integer, or -11 as a signed integer (your computer represents negative integers as Two's complement ). 这32位表示4294967285作为无符号整数,或-11表示有符号整数(您的计算机将负整数表示为二进制补码 )。 They can also mean a 32-bit floating point number or four 8-bit characters. 它们还可以表示32位浮点数或4个8位字符。

Bits don't have any "absolute" meaning. 比特没有任何“绝对”含义。 They can represent anything, depending on how you "look" at them (which type they have). 它们可以代表任何东西,具体取决于你“看”它们的方式(它们具有哪种类型)。

The ~ operator performs a ones-complement on its argument, and it does not matter whther the argument is a signed or unsigned integer. ~运算符在其参数上执行一个补码 ,并且无论参数是有符号还是无符号整数都无关紧要。 It merely flips all the bits, so 它只是翻转所有位,所以

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

becomes

1111 1111 1111 0101 (bin)

(where, presumably, these numbers are 32 bits wide -- I omitted 16 more 0's and 1's.) (据推测,这些数字是32位宽 - 我省略了16个0和1。)

How will cout display the result? cout将如何显示结果? It looks at the original type. 它查看原始类型。 For a signed integer, the most significant bit is its sign. 对于有符号整数,最重要的位是其符号。 Thus, the result is always going to be negative (because the most significant bit in 10 is 0 ). 因此,结果总是为 (因为10最重要的位是0 )。 To display a negative number as a positive one, you need the two's complement: inverting all bits, then add 1. For example, -1 , binary 111..111 , displays as (inverting) 000..000 then +1: 000..001 . 要将负数显示为正数,需要二进制补码:反转所有位,然后加1.例如, -1 ,二进制111..111 ,显示为(反转) 000..000然后+1: 000..001 Result: -1 . 结果: -1

Applying this to the one's complement of 10 you get 111..110101 -> inverting to 000...001010 , then add 1 . 将其应用于10的补码,得到111..110101 - >反转为000...001010 ,然后加1 Result: -11. 结果:-11。

For an unsigned number, cout doesn't do this (naturally), and so you get a large number: the largest possible integer minus the original number. 对于无符号数, cout不会(自然地)这样做,因此得到一个大数:最大可能整数减去原始数。

In memory there is stored 4294967285 in both cases (4294967296 properly a typo, 33 bit?), the meaning of this number depends which signdeness you use: 在内存中,在两种情况下都存储了4294967285(4294967296正确的拼写错误,33位?),这个数字的含义取决于您使用的标记:

  • if it's signed, this the number is -11. 如果它已签名,则该数字为-11。
  • if it's unsigned, then it's 4294967285 如果它是未签名的,那么它是4294967285

different interpretations of the same number. 对同一数字的不同解释。

You can reinterpret it as unsigned by casting it, same result: 您可以通过强制转换将其重新解释为unsigned,结果相同:

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

Try this 试试这个

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM