Range of signed char
Why the range of sig开发者_开发问答ned character is -128
to 127
but not -127
to 128
?
That is because of the way two's complement encoding works: 0 is treated as a "positive" number (signed bit off), so, therefore, the number of available positive values is reduced by one.
In ones' complement encoding (which is not very common nowadays, but in the olden days, it was), there were separate values for +0 and -0, and so the range for an 8-bit quantity is -127 to +127.
In 8-bit 2's complement encoding numbers -128
and +128
have the same representation: 10000000
. So, the designer of the hardware is presented with an obvious dilemma: how to interpret bit-pattern 10000000
. Formally, it will work either way. If they decide to interpret it as +128
, the resultant range will be -127..+128
. If they decide to interpret it as -128
, the resultant range will be -128..+127
.
In actual real-life 2's complement representation the latter approach is chosen because it satisfies the following nice convention: all bit-patterns with 1
in higher-order bit represent negative numbers.
It is worth noting though, that language specification does not require 2's-complement implementations to treat the 100...0
bit pattern as a valid value in any signed integer type. E.g. implementations are allowed to restrict 8-bit signed char
to -127..+127
range and regard 10000000
as an invalid bit combination (trap representation).
I think an easy way to explain this for the common soul is :
A bit is a value 0
or 1
, or 2 possibilities
A 2-bit holds two combinations or 0
and 1
for four possible values : 00
, 01
, 10
, and 11
.
A 3-bit holds three combinations for a total of eight possible values : 000
to 111
.
Thus n-bits holds n combinations for a total of 2^n possible values. Therefore, an 8-bit value is 2^8 = 256 possible values.
For signed numbers, the most significant bit (the first one reading the value from left to right) is the sign bit; that leaves a possibility of 2^(n-1) possible values. For an 8-bit signed number, this is 2^7 = 128 possible values for each sign. But since the positive sign includes the zero (0 to 127 = 128 different values, and 128 + 128 = 2^8 = 256), the negative sign includes -1 to... -128 for 128 different values also. Where :
10000000 = -128
...
11111111 = -1
00000000 = 0
...
01111111 = 127
#include <limits.h>
#include <stdio.h>
...
printf("range of signed character is %i ... %i", CHAR_MIN, CHAR_MAX );
If you just consider twos complement as arithmetic modulo 256, then the cutoff between positive and negative is purely arbitrary. You could just as well have put it at 63/-192, 254/-1, 130/-125, or anywhere else. However, as a standard signed integer format, twos complement came by convention put put the cutoff at 127/-128. This cutoff has one big benefit: the high bit being set corresponds directly to the number being negative.
As for the C language, it leaves the format of signed numbers up to the implementation, but only offers 3 choices of implementation, all of which use a "sign bit": sign/magnitude, ones complement, and twos complement.
If you look at ranges of chars and ints there seems to be one extra number on the negative side. This is because a negative number is always stored as 2’s compliment of its binary. For example, let us see how -128 is stored. Firstly, binary of 128 is calculated (10000000), then its 1’s compliment is obtained (01111111). A 1’s compliment is obtained by changing all 0s to 1s and 1s to 0s. Finally, 2’s compliment of this number, i.e. 10000000, gets stored. A 2’s compliment is obtained by adding 1 to the 1’s compliment. Thus, for -128, 10000000 gets stored. This is an 8-bit number and it can be easily accommodated in a char. As against this, +128 cannot be stored in a char because its binary 010000000 (left-most 0 is for positive sign) is a 9-bit number. However +127 can be stored as its binary 01111111 turns out to be a 8-bit number.
Step 1: If you take 2's complement of any number from 0 up to 127 the bit number 8 will always be 1. So lets reserve that info.
Step2 : if you find the -127 by applying 2's complement into +127 you will find "1 0 0 0 0 0 0 1" and finally if you substract 1 from this number then the smallest 8 bit number -128 will be achieved as "1 0 0 0 0 0 0 0"
As a result if we combine the info that we reserved at step 1 and the result from step2, we come to the conclusion that, the most significiant bit or bit number 8 in char containers must always be 1 so called signed bit.
精彩评论