user2912611
user2912611

Reputation: 544

1's complement using ~ in C/C++

I am using Visual Studio 2013.
Recently I tried the ~ operator for 1's complement:

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

Output is -11

But for

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

the output is 4294967296

I don't get why the output is -11 in the case of signed int. Please help me with this confusion.

Upvotes: 13

Views: 72007

Answers (4)

Ivan Kuckir
Ivan Kuckir

Reputation: 2549

When you put number 10 into 32-bit signed or unsigned integer, you get

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). They can also mean a 32-bit floating point number or four 8-bit characters.

Bits don't have any "absolute" meaning. They can represent anything, depending on how you "look" at them (which type they have).

Upvotes: 24

Agnit
Agnit

Reputation: 141

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

Upvotes: 1

Jongware
Jongware

Reputation: 22457

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.)

How will cout display the result? 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). 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. Result: -1.

Applying this to the one's complement of 10 you get 111..110101 -> inverting to 000...001010, then add 1. Result: -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.

Upvotes: 4

user1129665
user1129665

Reputation:

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:

  • if it's signed, this the number is -11.
  • if it's unsigned, then it's 4294967285

different interpretations of the same number.

You can reinterpret it as unsigned by casting it, same result:

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

Upvotes: 2

Related Questions