6

There's something I dont get:

A signed char in C is represented on 8 bits:00000000

  • 0 is 0000 0000 => 0
  • 1 is 0000 0001 => 1
  • ...
  • 127 is 0111 1111 => 127

So I thought the 8th bits is the sign bit. So I thought:

  • 128 is 1000 0000 => 0
  • 129 is 1000 0001 => -1

But no!

Try this:

int main(int argc, const char *argv[])
{
    int i;
    for (i = 0; i < 256; i++) {
        printf("%3d = %d\n", i, (signed char)i);
    }
    return 0;
}

And you get: gcc -o tt tt.c ; ./tt | more

  • ...
  • 126 = 126
  • 127 = 127
  • 128 = -128
  • 129 = -127
  • 130 = -126
  • 254 = -2
  • 255 = -1

How comes?

Olivier Pons
  • 15,363
  • 26
  • 117
  • 213
  • 9
    Read about [Two's complement](http://en.wikipedia.org/wiki/Two%27s_complement). – Some programmer dude Aug 02 '13 at 09:40
  • 1
    [What is `-(-128)` for signed single byte char in C?](http://stackoverflow.com/questions/17469804/what-is-128-for-signed-single-byte-char-in-c/17469941#17469941) – Grijesh Chauhan Aug 02 '13 at 09:41
  • 1
    The sign-magnitude scheme you're describing does exist, but it's rare for integers because it complicates arithmetic. Two's complement lets many operations be signedness-independent. – harold Aug 02 '13 at 09:48
  • @GrijeshChauhan Remarkably undefined, if you limit yourself to 8 bits (it's not an expressible number, but if you blindly apply the rules for how to negate a number using 2-complement, you end up with -(-128) -> -128. – Vatine Aug 02 '13 at 10:32
  • @Vatine you are correct bit overflow is Undefined, its actually implementation-defined because a trap representation. I just tried to answer on particular output. – Grijesh Chauhan Aug 03 '13 at 10:58

5 Answers5

8

This is called the 2's complement representation of signed integers and is used for all integer types.

The idea is this: The adder in the CPU simply ignores when an overflow happens and wraps around, so you are actually calculating on a modulo ring of numbers. So, if you subtract 1 from zero, you get

 00000000 = 0
-00000001 = 1
--------------
 11111111 = -1

and so on.

That way, your computer can simply ignore signs while calculating. This is even true for multiplications, as in this example multiplication of 3 and -2 (4-bit arithmetic for brevity):

0011 * 1110
-----------
       0000
      0011
     0011
    0011
-----------
     101010
truncated to 4 bits: 1010

1010 is the negative of 0110, which is 6, so the result is -6 as it should be.

There are only very few points where signedness needs to be taken into account, like comparisons, divisions and casts to larger integer types. Comparisons are relatively straightforward, casts work like this:

00000001 -> 0000000000000001
10000000 -> 0000000010000000 (unsigned extension 128 -> 128)
10000000 -> 1111111110000000 (sign extension, the sign bit is copied into all new bits, preserving the value of negative numbers -128 -> -128)
cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • @glglgl You mean this: `10000000 -> 0000000010000000`? No, it's not wrong, its the _unsigned_ extension. – cmaster - reinstate monica Aug 02 '13 at 09:56
  • Ok, I misread it. I read it as a claim that `-00000001 = 1`, which is not true. I didn't understand that it is the `-` sign for the complete line. – glglgl Aug 02 '13 at 10:33
  • But to your last claim - there are two more points: multiplication and division. `x / -1` is something else than `x / 255`. The same counts for `x * -1` vs. `x * 255`. – glglgl Aug 02 '13 at 10:34
  • @glglgl I believe you are right about divisions, sorry I forgot about those. But for the multiplication case, my assertion holds true because anything times 2^n will have its last n bits clear. If you take one away from this factor, you subtract the other factor from the result, which is its negative in 2's complement representation. It's really amazing how easy it is to calculate in 2's complement... – cmaster - reinstate monica Aug 02 '13 at 11:28
  • Oops - I think you are right. Indeed, 256 * 255 and 256 * -1 both result in 0xFF00... – glglgl Aug 02 '13 at 13:24
5

This is because of 8 bit 2's compliment encoding.Signed character range is from -128 to 127.

EDIT1: Response to @Grijesh's comment

-128 and +128 have the same representation: 10000000.So to avoid confusion and to make a rule All bit-patterns with 1 in higher-order bit represent negative numbers it is decided to consider it as -128 which makes range from -128 to 127 rather than -127..+128.

Dayal rai
  • 6,548
  • 22
  • 29
  • 2
    + but I think OP need more details, you should show how 2's complement works in one byte and `-128 = 128` that is the reason `127` + `1` gives `-128`. you may find the linked answer I given to question. – Grijesh Chauhan Aug 02 '13 at 10:09
  • 1
    @GrijeshChauhan Edited as per your suggestion and accept my +1 on that link too :) i avoided this earlier because question was not about why not -127 to 128? – Dayal rai Aug 02 '13 at 10:49
4

In two's complement, the left-most bit is negative, and the others positive, so

1000 0000

=> -128

and

1000 0001

=> -128 + 1 = -127

Therefore the largest number is 0111 1111 (127) and smallest is 1000 0000 (-128)

Rob
  • 208
  • 1
  • 2
  • 9
2

You can think signed datatypes as a clock. It will always hit 12 O clock after 12 hours. Char range is -128 to +127. So as you hit 127 according to my clock rule next hit will be -128.

I suggest you to do some binary calculation.

For more information read http://en.wikipedia.org/wiki/Two%27s_complement

someone
  • 1,638
  • 3
  • 21
  • 36
1

In c char is the only 1 byte memory allocate means totally 8 bit. This is because of 8 bit 2's compliment encoding.Signed character range is from -128 to 127.
because you used.

   printf("%3d = %d\n", i, (signed char)i);
Mohsin Shaikh
  • 494
  • 1
  • 4
  • 11