Thread: Missing basics of signed and unsigned numbers

1. Missing basics of signed and unsigned numbers

If i write a program like this
Code:
```int main(int argc, char const *argv[])
{
unsigned char value=200;
printf ("%d",(signed char)value);
return 0;
}```
suppose if i do
Code:
```int main(int argc, char const *argv[])
{
unsigned char value=200;
printf ("%u",(signed char)value);
return 0;
}```

2. This might help...

Negative numbers in C

3. Internally there is no such thing as "signed" integers... All values are writen in a group of 8 bits (char type) but can be represented as "signed" using something called "complement 2". It works this way:

With 8 bits you can have values, in binary, from 0b00000000 to 0b11111111 (0 to 255). If you want to deal with "signed" values you must split this range in 2. Using the highest bit as a signed (0 = +, 1 = -) you get values from 0x00 to 0x7f (+0 to +127) and from 0x80 to 0xff (-128 to -1). Notice the second half is backwards. How so?

What happens if you subtract 0x01 from 0x00? In binary you'll get 0xff (all bits set), so 0xff (0b11111111) is -1. You can use one simple rule (difficult to explain briefly): When a value has its highest bit set, invert every bit and add 1 to get the absolute representation... For instance, +1 is 0b00000001, inverting you'll get 0b11111110, and adding 1 you'll get 0b11111111.

Code:
```⁣⁣⁣⁣----|--|--...--|--|--|--|--|--|--|--...--|--|----
-128 -127     -3 -2 -1  0 +1 +2 +3  ...+126 +127```
If you walk the line to the left you are subtracting 1 from the previous value, if you walk to the right, you are adding... What happens if you add +1 to +127. Suddenly, 0b01111111 (+127) will become 0b1000000 (+128), but if we use the "complement 2" rule this represents -128. If we keep adding +1 there is a point where 0b11111111 (-1) will become 0 (0b00000000).
We can do this to the other side (to the left), subtracting 1 from the previous value, so 0b00000001 (+1) will become 0b00000000 (0)... then subtracting once more, we'll get 0b11111111 (-1).

When you use "%d" on printf(), the value is interpreted as "signed integer" and follow this "complement 2" rule... When you use "%u" no "complement 2" is used... So 200 is 0b11001000. Using "complement 2" you can see the higherst bit is 1, so this value represent a negative number. Which one? Well... inverting and adding 1 we get 0b00111000, or 0x38 (56), so 200 (unsigned) when assigned to a signed type becomes -56.

Notice the BINARY representation is the same (0b11001000), but it means a positive number in unsigned types, and a negative number in signed types...

Second, you'll need to understand how the CPU works to get this low level thinking. To the CPU, the only difference between a signed and unsigned number is how it is assumed to be either. The compiler is much clearer about this, so mixing signed and unsigned values is often a source of bugs. When it's required you take some responsibility to ensure what you're doing makes sense, so the knowledge you're seeking is valuable.

It is also the subject of study, and not entirely appropriate for a post here, it becomes a book.

However, your last code represents a serious bug. The size of the char is 8 bits, but the unsigned integer you've specified in printf expects a larger integer (depending on the platform you're writing in). You've basically told the printf function to look way beyond the storage of the char and give you garbage.

printf can be "dangerous" in this way. Some compilers attempt to examine the format arguments to see if your parameters make sense, some don't. If the compiler warned you but you ignored the warning, you'll want to start responding to the warnings before you create crashes.

5. The way I originally got my head around signed integers was when a professor if mine said, "On an analogue clock there are 2 ways to get from 2-o-clock to 1-o-clock: You can either subtract 1 hour, or you could add 11 hours"

Looking at a clock I could clearly see that the 11 could be considered -1.

Integers do the same thing

6. Originally Posted by Click_here
The way I originally got my head around signed integers was when a professor if mine said, "On an analogue clock there are 2 ways to get from 2-o-clock to 1-o-clock: You can either subtract 1 hour, or you could add 11 hours"

Looking at a clock I could clearly see that the 11 could be considered -1.
That's a great tip.