Thread: Missing basics of signed and unsigned numbers

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    35

    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;
    }
    The answer reads -56. How does this come?
    suppose if i do
    Code:
    int main(int argc, char const *argv[])
    {
    unsigned char value=200;
    printf ("%u",(signed char)value);
    return 0;
    }
    It reads a big value. I am not understanding the basics of this. Please help.

  2. #2
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    This might help...

    Negative numbers in C

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    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.

    Another way to think about this is to draw a line:
    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...
    Last edited by flp1969; 05-27-2019 at 05:45 PM.

  4. #4
    Registered User
    Join Date
    May 2019
    Posts
    214
    First, read Click_here's link.

    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. #5
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    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. #6
    Registered User catacombs's Avatar
    Join Date
    May 2019
    Location
    /home/
    Posts
    81
    Quote Originally Posted by Click_here View Post
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Signed and unsigned
    By ncode in forum C Programming
    Replies: 3
    Last Post: 09-02-2011, 08:59 PM
  2. Unsigned vs. Signed?
    By Programmer_P in forum C++ Programming
    Replies: 4
    Last Post: 12-22-2009, 01:15 PM
  3. Binary numbers, signed, unsigned.
    By JOZZY& Wakko in forum Tech Board
    Replies: 14
    Last Post: 11-20-2009, 02:31 AM
  4. signed vs unsigned
    By char in forum C Programming
    Replies: 1
    Last Post: 04-24-2002, 01:10 PM
  5. Difference between unsigned and signed numbers...
    By Nutshell in forum C Programming
    Replies: 8
    Last Post: 01-26-2002, 09:48 AM

Tags for this Thread