为什么签名字符的范围是-128
到127
而不是-127
到128
?
答案 0 :(得分:27)
这是因为two's complement编码的工作方式:0被视为“正”数(有符号位关),因此,可用正值的数量减少了一个。
在ones' complement编码中(现在不是很常见,但在过去,它是),+ 0和-0有单独的值,因此8位数的范围是-127到+127。
答案 1 :(得分:14)
在8位2的补码编码中,-128
和+128
具有相同的表示形式:10000000
。因此,硬件设计者面临着一个明显的困境:如何解释位模式10000000
。在形式上,它将以任何一种方式工作。如果他们决定将其解释为+128
,则结果范围将为-127..+128
。如果他们决定将其解释为-128
,则结果范围将为-128..+127
。
在实际的2的补码表示中选择后一种方法,因为它满足以下很好的约定:高阶位中1
的所有位模式都代表负数。
值得注意的是,语言规范不要求二进制补码实现将100...0
位模式视为任何有符号整数类型中的有效值。例如。允许实现将8位signed char
限制为-127..+127
范围,并将10000000
视为无效位组合(陷阱表示)。
答案 2 :(得分:7)
我认为为共同的灵魂解释这个问题的一个简单方法是:
位是值0
或1
,或2种可能性
2位包含两个组合,或0
和1
有四个可能的值:00
,01
,10
和{{1} }。
3位包含三种组合,总共有八种可能的值:11
到000
。
因此,n位保持n个组合,总共2 ^ n个可能的值。因此,8位值是2 ^ 8 = 256个可能的值。
对于带符号的数字,最高有效位(从左到右读取值的第一个)是符号位;这留下了2 ^(n-1)个可能值的可能性。对于8位有符号数,对于每个符号,这是2 ^ 7 = 128个可能的值。但由于正号包括零(0到127 = 128个不同的值,而128 + 128 = 2 ^ 8 = 256),因此对于128个不同的值,负号包括-1到...... -128。地点:
111
答案 3 :(得分:3)
#include <limits.h>
#include <stdio.h>
...
printf("range of signed character is %i ... %i", CHAR_MIN, CHAR_MAX );
答案 4 :(得分:1)
如果你只考虑二进制补码作为算术模256,那么正负之间的截止是纯粹随意的。您也可以把它放在63 / -192,254 / -1,130 / -125或其他任何地方。但是,作为标准的有符号整数格式,通过惯例将二进制补码放在127 / -128。这个截止值有一个很大的好处:设置的高位直接对应于负数。
对于C语言,它将签名数字的格式留给实现,但只提供3种实现选择,所有选项都使用“符号位”:符号/幅度,补码和二进制补码。
答案 5 :(得分:1)
如果你看一下字符和整数的范围,那么在消极方面似乎还有一个额外的数字。这是因为负数始终存储为2的二进制补码。例如,让我们看看如何存储-128。首先,计算128的二进制(10000000),然后获得其1的补码(01111111)。通过将所有0更改为1并将1更改为0来获得1的恭维。最后,存储2号对这个数字的补充,即10000000。通过在1的赞美中加1来获得2的赞美。因此,对于-128,10000000被存储。这是一个8位数字,可以轻松容纳在字符中。与此相反,+ 128不能存储在char中,因为它的二进制010000000(最左边的0表示正号)是一个9位数。但是可以存储+127,因为它的二进制01111111结果是8位数。