-1

I have the following code in c:

 unsigned int a = 60; /* 60 = 0011 1100 */ int c = 0; c = ~a; /*-61 = 1100 0011 */ printf("c = ~a = %d\n", c ); c = a << 2; /* 240 = 1111 0000 */ printf("c = a << 2 = %d\n", c ); 

The first output is -61 while the second one is 240. Why the first printf computes the two's complement of 1100 0011 while the second one just converts 1111 0000 to its decimal equivalent?

5
  • 1
    @Babbleshack no it couldn't. It's about an assumption this person has made about the width of an int. Commented Feb 3, 2014 at 22:53
  • @paddy good job i made it a comment then. I should have spent more time thinking about the question sorry about that, ill delete it. Commented Feb 3, 2014 at 22:54
  • 1
    c would have a value of 1111 1111 1111 1111 1111 1111 1100 0011. ~ complements all the bits, not just those you list in the first line. Commented Feb 3, 2014 at 22:56
  • 1
    As @paddy implied, your int is (probably) 4 bytes, not 1 byte. Therefore, ~a = 11111111 11111111 11111111 11000011, but a << 2 = 00000000 00000000 00000000 11110000. Commented Feb 3, 2014 at 22:56
  • 2
    And note that c, the value being printed, is declared as signed, and the % format code is for signed printing, so c is naturally interpreted as a signed 2's complement number. Commented Feb 3, 2014 at 22:59

2 Answers 2

6

You have assumed that an int is only 8 bits wide. This is probably not the case on your system, which is likely to use 16 or 32 bits for int.

In the first example, all the bits are inverted. This is actually a straight inversion, not two's complement:

1111 1111 1111 1111 1111 1111 1100 0011 (32-bit) 1111 1111 1100 0011 (16-bit) 

In the second example, when you shift it left by 2, the highest-order bit is still zero. You have misled yourself by depicting the numbers as 8 bits in your comments.

0000 0000 0000 0000 0000 0000 1111 0000 (32-bit) 0000 0000 1111 0000 (16-bit) 
Sign up to request clarification or add additional context in comments.

1 Comment

Not only on older systems. On most 8- and 16 bit systems nowadays, it is still 16 bits, e. g. on many µCs.
0

Try to avoid doing bitwise operations with signed integers -- often it'll lead you into undefined behavior.

The situation here is that you're taking unsigned values and assigning them to a signed variable. For ~60 this is undefined behavior. You see it as -61 because the bit pattern ~60 is also the two's-complement representation of -61. On the other hand 60 << 2 comes out correct because 240 has the same representation both as a signed and unsigned integer.

9 Comments

ITYM ones complement?
@PaulR no, ~60 is the twos complement representation of -61 - it's the ones complement representation of -60
@PaulR No... two's complement. Think about it, ~1 is 11111110 (sign extended for word size); that is -2. ~60 is -61. Reconsider your downvote? (Also, other downvoter please comment?)
It's not undefined behavior -- the bit operations are completely defined. The only thing "undefined" is whether the machine is 1s complement or 2s complement, and if that is known the behavior is completely defined.
I think what happened here is you confused the part in the C standard that talks about right-shifting negative signed values, which is implementation dependent. Whereas left-shifting any signed value is well defined.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.