0

In a TC++ compiler, the binary representation of 5 is (00000000000000101). I know that negative numbers are stored as 2's complement, thus -5 in binary is (111111111111011). The most significant bit (sign bit) is 1 which tells that it is a negative number.

So how does the compiler know that it is -5? If we interpret the binary value given above (111111111111011) as an unsigned number, it will turn out completely different?

Also, why is the 1's compliment of 5 -6 (1111111111111010)?

8 Answers 8

8

The compiler doesn't know. If you cast -5 to unsigned int you'll get 32763.

Sign up to request clarification or add additional context in comments.

5 Comments

Yep, the cast tells the compiler how to interpret bits at a certain memory location. Generally it has its own idea of what resides where, but a cast throws a wrench into things.
Well, you don't even have to do explicit cast.
yeah the compiler just does the math. if u cast -5 to unsigned int, result is always UINT_MAX+1-5, whether it has sign-magnitude/two-complement/one complement is irrelevant.
Wait, doesn't that mean the compiler does know? The cpu just does the math and the compiler interprets the result as signed or unsigned. Is that right?
If i use signed int a = 2 , then how does the compiler knows it is a negative number or a positive number?
5

The compiler knows because this is the convention the CPU uses natively. Your computer has a CPU that stores negative numbers in two's complement notation, so the compiler follows suit. If your CPU supported one's complement notation, the compiler would use that (as is the case with IEEE floats, incidentally).

The Wikipedia article on the topic explains how two's complement notation works.

1 Comment

+1: Quote some useful docs; +1: it's hardware; +1: the compiler doesn't "know" anything about the number -- you declared it signed or unsigned -- you have to then use it consistently with the declaration.
3

The processor implements signed and unsigned instructions, which will operate on the binary number representation differently. The compiler knows which of these instructions to emit based on the type of the operands involved (i.e. int vs. unsigned int).

The compiler doesn't need to know if a number is negative or not, it simply emits the correct machine or intermediate language instructions for the types involved. The processor or runtime's implementation of these instructions usually doesn't much care if the number is negative or not either, as the formulation of two's complement arithmetic is such that it is the same for positive or negative numbers (in fact, this is the chief advantage of two's complement arithmetic). What would need to know if a number is negative would be something like printf(), and as Andrew Jaffe pointed out, the MSBit being set is indicative of a negative number in two's complement.

1 Comment

If i write signed int a = -1 , then ` -1` in 2's complement form is 11111111 11111111 11111111 11111111 and then when i use %d to interpret it it prints -1 and %u , it prints 4294967295 and when i write signed int a = 2 , it prints 2 when i use %d and also when i use %u . If 2 would be in two's complement it would be 11111111 11111111 11111111 11111101 , and then it would be a very diffr answer , what i really want to ask is when does 2's complement happen is it depend on - sign or it happens for every integer if type is signed int which must not be the case here.
2

The first bit is set only for negative numbers (it's called the sign bit)

Detailed information is available here

1 Comment

But for unsigned int first bit can be set and it is still positive number.
2

The kewl part of two's complement is that the machine language Add, and Subtract instructions can ignore all that, and just do binary arithmetic and it just works...

i.e., -3 + 4

in Binary 2's complement, is

   1111 1111 1111 1101   (-3)
+  0000 0000 0000 0100   ( 4)
   -------------------
   0000 0000 0000 0001   ( 1)

2 Comments

You know, I completely forgot about that property of 2's complement. That's probably another good reason why it was invented.
If i write signed int a = -1 , then -1 in 2's complement form is 11111111 11111111 11111111 11111111 and then when i use %d to interpret it it prints -1 and %u , it prints 4294967295 and when i write signed int a = 2 , it prints 2 when i use %d and also when i use %u . If 2 would be in two's complement it would be 11111111 11111111 11111111 11111101 , and then it would be a very diffrenet answer , what i really want to ask is when does 2's complement happen is it depend on - sign or it happens for every integer if type is signed int which must not be the case here.
2

let us give an example: we have two numbers in two bytes in binary: A = 10010111 B = 00100110 (note that the machine does not know the concept of signed or unsigned in this level)

now when you say "add" these two, what does the machine? it simply adds:

R = 10111101 (and carry bit : 1)

now, we -as compiler- need to interpret the operation. we have two options: the numbers can be signed or unsigned.

1- unsigned case: in c, the numbers are of type "unsigned char" and the values are 151 and 38 and the result is 189. this is trivial.

2 - signed case: we, the compiler, interpret the numbers according to their msb and the first number is -105 and the second is still 38. so -105 + 38 = -67. But -67 is 10111101. But this is what we already have in the result (R)! The result is same, the only difference is how the compiler interprets it.

The conclusion is that, no matter how we consider the numbers, the machine does the same operation on the numbers. But the compiler will interpret the results in its turn.

Note that, it is not the machine who knows the concept of 2's complement. it just adds two numbers without caring the content. The compiler, then, looks at the sign bit and decides.

When it comes to subtraction, this time again, the operation is unique: take 2's complement of the second number and add the two.

Comments

1

If the number is declared as a signed data type (and not type cast to an unsigned type), then the compiler will know that, when the sign bit is 1, it's a negative number. As for why 2's complement is used instead of 1's complement, you don't want to be able to have a value of -0, which 1's complement would allow you to do, so they invented 2's complement to fix that.

1 Comment

I believe the real reason was to allow machine language add/subtract algorithms to ignore the sign of the oeprands and simply do a bitwise addition or subtraction, carrying bit when necessary...
0

It's exactly that most significant bit -- if you know a number is signed, then if the MSB=1 the compiler (and the runtime!) knows to interpret it as negative. This is why c-like languages have both integers (positive and negative) and unsigned integers -- in that case you interpret them all as positive. Hence a signed byte goes from -128 to 127, but an unsigned byte from 0 to 255.

1 Comment

Actually, a signed byte goes from -128 to 127.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.