9

§5.2.4.2.1 of C99 defines SCHAR_MIN as -127 and SCHAR_MAX as 127. Should not the range for an 8 bit signed integer be -128 to +127?

The limits.h for my compiler defines SCHAR_MIN as (-1 << ((CHAR_BIT)-1)), which is -128 given CHAR_BIT is 8.

Is there any reason why SCHAR_MIN was defined -127 and not -128 ?

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
Summit Raj
  • 820
  • 5
  • 10

1 Answers1

28

It doesn't actually define SCHAR_MIN as -127, it defines the minimum range of signed characters to -127..127.

It does this because it has to be able to handle the other two encoding schemes for signed numbers, those being ones' complement and sign/magnitude. Both of these have a positive and negative zero, stealing away the -128 you find in two's complement.

ISO C (C99), section 6.2.6.2/2, states that an implementation must choose one of these three different representations for signed integral data types:

  • two's complement;
  • ones' complement; or
  • sign/magnitude

The two's complement implementations far outweigh the others but the others do exist.

In all those representations, positive numbers are identical, the only difference being the negative numbers.

To get the negative representation for a positive number, you:

  • invert all bits then add one for two's complement.
  • invert all bits for ones' complement.
  • invert just the sign bit for sign/magnitude.

You can see this in the table below, for both 5 and 0:

number | two's complement    | ones' complement    | sign/magnitude
=======|=====================|=====================|====================
     5 | 0000 0000 0000 0101 | 0000 0000 0000 0101 | 0000 0000 0000 0101
    -5 | 1111 1111 1111 1011 | 1111 1111 1111 1010 | 1000 0000 0000 0101
       |                     |                     |
     0 | 0000 0000 0000 0000 | 0000 0000 0000 0000 | 0000 0000 0000 0000
    -0 | 0000 0000 0000 0000 | 1111 1111 1111 1111 | 1000 0000 0000 0000
           (no difference)        (both of these have distinct +/-0)
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 3
    Technically, it is *Ones'* complement, not *One's* complement. There is a difference :-). – Alok Singhal Nov 04 '11 at 13:44
  • 2
    My reference is *The Art of Computer Programming*. The difference being that *Ones'* complement is with respect to a long string of ones, whereas *Two's* complement is not with respect to a long string of twos. – Alok Singhal Nov 04 '11 at 14:17
  • @Alok: my authority was the top eight hits on Google :-) But I checked volume 2 of TAOCP and you're right. I'd also be more inclined to listen to Knuth than a _hundred_ internet pages, so I'll modify it. I would note that the ISO standard itself uses Knuth's notation. Or should that be Knuths' notation? :-) – paxdiablo Nov 04 '11 at 14:36
  • 11
    @paxdiablo: It should be Knuths' only if you're referring to a long string of Knuths. – Keith Thompson Dec 17 '11 at 21:17
  • You take a one's complement for each digit, so the entire number is a complement of many ones, making it ones' complement. – n. m. could be an AI Mar 27 '17 at 05:18
  • Have there ever actually been any conforming implementations where the number of values for `char` was not a power of 2, or where the number of values for `signed char` was not at least 256? – supercat Apr 04 '17 at 23:21
  • @supercat: http://stackoverflow.com/questions/12276957/are-there-any-non-twos-complement-implementations-of-c – paxdiablo Apr 05 '17 at 02:01
  • @paxdiablo: The one non-two's-complement machine I saw there was a 36-bit machine whose `char` type is unsigned and holds 512 distinct values, and whose signed char type holds 511 values. – supercat Apr 05 '17 at 14:41