# Thread: Negative numbers in C

1. ## Negative numbers in C

hey everyone. i had this question going in my mind about negative numbers and how they are stored in memory.i have read that in order to obtain the negative of a number , the 2's compliment is taken and added a 1 to it.

for example if we have a variable char that has number 1 in it.
=> 0001

to get -1 => 1110 (2's..) =>add 1=> 1111

But how is it possible know that 1111 is not a 15 and it is -1 ...

As for my 2nd question .. if a type conversion should occur from a char to an int during some operation it would b machine dependent to make the char an unsigned int (by adding zeros at the back) or by making it signed. My question is , how will it be signed i mean what operation would it undergo to achieve it.

Thank you. 2. But how is it possible know that 1111 is not a 15 and it is -1 ...
It can actually be either 15 or -1, depending on interpretation. "Data is what you define it to be."

If you use it as a signed integer, it's -1, otherwise it's 15.

Oh and, in modern computers, bits are stored in groups of 8 (called bytes). So, if you are using a char to store it, 1 would be 00000001, and its 2's complement would be 11111111. We usually call the most-significant-bit (the one on the left) the "sign bit". If it's 1, the number is negative, vice versa.

To the computer its just a sequence of bits. Whether they "are" -1 or 255 would depend on how you use them.

As for my 2nd question .. if a type conversion should occur from a char to an int during some operation it would b machine dependent to make the char an unsigned int (by adding zeros at the back) or by making it signed. My question is , how will it be signed i mean what operation would it undergo to achieve it.
That would depend on whether char is signed or unsigned (which is implementation-defined). If it is unsigned, it will be zero-extended to make the int (all upper 24 bits set to 0). If it is signed, it will be "sign-extended" (all upper 24 bits set to the MSB of the char). 3. Originally Posted by BlaX hey everyone. i had this question going in my mind about negative numbers and how they are stored in memory.i have read that in order to obtain the negative of a number , the 2's compliment is taken and added a 1 to it.

for example if we have a variable char that has number 1 in it.
=> 0001

to get -1 => 1110 (2's..) =>add 1=> 1111

But how is it possible know that 1111 is not a 15 and it is -1 ...

Thank you.
Negative numbers are stored as 2's complement of its positive part. By the way after changing 0 to 1 and vice versa you dont get the 2's complement but the 1's complement, so in your example 1110 is the 1's complement and after adding 1 to the 1's complement you get a 2's complement.
1111 will be a negative number coz the MSB is used to know whether the number is actually negative or a positive. If the MSB is 1 it's terated as negative and if 0 it's treated as positive. Also as cyberfish pointed out the char is taken as 8bits in most of the compilers today. 4. Originally Posted by cyberfish Oh and, in modern computers, bits are stored in groups of 8 (called bytes). So, if you are using a char to store it, 1 would be 00000001, and its 2's complement would be 11111111. We usually call the most-significant-bit (the one on the left) the "sign bit".
And the lowest negative number, -128, is 10000000. The reason 1111 signed would be -1 is because the most significant bit (the sign bit) is set; 00001111 would still be 15, but that is contrasting an eight bit number with a four bit one. With a signed type, all numbers with the MSB set are negative, all numbers without the MSB set are positive.

The only confusing part about it is that the value of the actual "value bits" (0-7) is reversed with negative numbers*; why -1 should be 11111111 instead of 10000001 and -128 10000000 instead of 11111111 I don't know -- maybe it makes arithmetic simpler for the processor.

*or (even more confusing) the reverse of the total value +1 5. Originally Posted by MK27 The only confusing part about it is that the value of the actual "value bits" (0-7) is reversed with negative numbers*; why -1 should be 11111111 instead of 10000001 and -128 10000000 instead of 11111111 I don't know -- maybe it makes arithmetic simpler for the processor.
I remember when they used to teach people "subtraction with borrowing" in school. 6. If you use it as a signed integer, it's -1, otherwise it's 15.
Let's say you have a variable int x=-1

=> it is stored as 11111111 in memory ... if we add 1 to x ... how can we determine if the answer is 0 or 256 ?

usually call the most-significant-bit (the one on the left) the "sign bit". If it's 1, the number is negative, vice versa.
1111 will be a negative number coz the MSB is used to know whether the number is actually negative or a positive. If the MSB is 1 it's terated as negative and if 0 it's treated as positive.
even the msb won't let us now if 11111111 is 255 or -1 .

If it is signed, it will be "sign-extended" (all upper 24 bits set to the MSB of the char).
if we're talking about a char the maximum bits lets say is 8 ...
Thought I didn't understand what u meant by saying all the upper bits are set to the MSB. 7. it is stored as 11111111 in memory ... if we add 1 to x ... how can we determine if the answer is 0 or 256 ?
In this case it will overflow and give you 0 in both cases (a char stores up to 255).

However, generally, both "cases" will also have the same binary representation. That's the beauty of 2's complement.

For example, if you have 10000001, which can be either -127 or 129, if you add 3 to it, you get -124 (10000100) or 132 (10000100). Same binary representation!

even the msb won't let us now if 11111111 is 255 or -1 .
It lets you know the sign of the number IF YOU CHOOSE TO INTERPRET IT AS SIGNED.

if we're talking about a char the maximum bits lets say is 8 ...
Thought I didn't understand what u meant by saying all the upper bits are set to the MSB.
Say you want to extend 10011001 to 16 bits.

Zero extension -
00000000 10011001
The upper bits are simply set to 0.

Sign extension -
11111111 10011001
The upper bits are set to the MSB of the original byte (the leftmost 1). 8. For example, if you have 10000001, which can be either -127 or 129, if you add 3 to it, you get -124 (10000100) or 132 (10000100). Same binary representation!
Let's say that number is stored in a signed char variable x and we want to print it.

Code:
`printf("%d",x);`
should i get -124 or 132 ?

what makes it be -124 or 132 ... knowing that it is a signed char

It lets you know the sign of the number IF YOU CHOOSE TO INTERPRET IT AS SIGNED.
Let's say we declared the variable as a signed char... which is signed.
But in what way will 10000100 be -124 or 132. 9. Originally Posted by BlaX
what makes it be -124 or 132 ... knowing that it is a signed char
Well, assume 8 bit bytes with a 2's complement binary representation. So, the range for a signed char is [-128,127]. Since 129 is out of the range, the initial value must be -127. This determining of the range would be based on what has been told to you earlier in this thread. Originally Posted by BlaX
should i get -124 or 132 ?
Thus the answer is obviously -127 + 3 = -124. 10. should i get -124 or 132 ?

what makes it be -124 or 132 ... knowing that it is a signed char
The fact that you defined it to be (by default or explicitly) signed or unsigned.

Let's say we declared the variable as a signed char... which is signed.
But in what way will 10000100 be -124 or 132.
If you interpret it as signed, it has to be -124. The MSB gives you the sign (negative) in this case, and the 2's complement gives you the magnitude (124). 11. Originally Posted by BlaX Let's say you have a variable int x=-1

=> it is stored as 11111111 in memory ... if we add 1 to x ... how can we determine if the answer is 0 or 256 ?

even the msb won't let us now if 11111111 is 255 or -1 .
If you add 1 to -1 obviously you'll get a 0. And this addition also results in the carry bit being set i.e carry now becomes 1. But the actual magnitude will be the 8bits starting from LSB.
If you are taking char to be signed then 11111111 will be -1 coz signed char has a range of -128 to 127 and this way the MSB decides it that the number is negative but on the other hand if you take char to be unsigned then it'll obviously be 255 coz unsigned has a range of 0 to 255 and in case of unsigned the MSB is doesn't signify anything(coz it's already without a sign). 12. >> i have read that in order to obtain the negative of a number , the 2's compliment is taken and added a 1 to it

The terminology is just a bit off there. To obtain the twos-compliment representation of a number you find its ones-compliment (negate each bit) and then add one.

>> why -1 should be 11111111 instead of 10000001 and -128 10000000 instead of 11111111 I don't know -- maybe it makes arithmetic simpler for the processor.

Right. The advantage of using twos-compliment is that it simplifies hardware logic in that it allows subtraction to be implemented as addition, and it works identically for signed and unsigned interpretations. For example, let's say we're dealing with 8-bit signed quantities, and we want to perform the operation 13 - 6:

Code:
```  0000 1101 (13)
- 0000 0110 (6)```
After obtaining the twos-compliment of 6 we can now just add the two numbers together:

Code:
```  0000 1101 (13)
+ 1111 1010 (-6)```
The initial result is:

Code:
`1 0000 0111`
But since we're working with 8-bit numbers the carry is discarded and the final result is 0000 0111 (7).

Notice that had the subtrahend been -6 (1111 1010) the same procedure would have produced 0001 0011 (19), eg: 13 - (-6) == 13 + 6 == 19.

Also note that had the first problem been 6 - 13, the logic is still the same:

Code:
```  0000 0110 (6)
- 0000 1101 (13)```
After twos-compliment:

Code:
```  0000 0110 (6)
+ 1111 0011 (-13)```
The result, of course, is 1111 1001 (-7). Naturally, if these had been unsigned 8-bit quantities the interpretation of 1111 1001 would be 249. 13. Originally Posted by BlaX Let's say that number is stored in a signed char variable x and we want to print it.

Code:
`printf("%d",x);`
should i get -124 or 132 ?

what makes it be -124 or 132 ... knowing that it is a signed char

Let's say we declared the variable as a signed char... which is signed.
But in what way will 10000100 be -124 or 132.
Since you passed %d to printf(), and %d means a signed integer, it would interpret x as a negative number. If you passed %u instead, then it should interpret it as an unsigned integer. 14. thank you all for your answers. i really understood everything you said. Appreciated.

Say you want to extend 10011001 to 16 bits.

Zero extension -
00000000 10011001
The upper bits are simply set to 0.

Sign extension -
11111111 10011001
The upper bits are set to the MSB of the original byte (the leftmost 1).
I was wondering .. where do these conversions take place ? im sure they won't be at the memory level because that will cause overriding and overflows in memory ... is it in the registers ?
Anyway why should they be converted afterall?Whats the purpose behind it.
Thank you 15. Originally Posted by BlaX thank you all for your answers. i really understood everything you said. Appreciated.

I was wondering .. where do these conversions take place ? im sure they won't be at the memory level because that will cause overriding and overflows in memory ... is it in the registers ?
Anyway why should they be converted afterall?Whats the purpose behind it.
Thank you
If you want to operate on a number (add to it, subtract, multiply, etc.) generally that number has to be put in a register first, and registers nowadays are longer than one byte. Popular pages Recent additions 