签名字符范围

问题描述 投票:16回答:6

为什么签名字符的范围是-128127而不是-127128

c
6个回答
27
投票

这是因为two's complement编码的工作方式:0被视为“正”数(有符号位关),因此,可用正值的数量减少了1。

ones' complement编码中(现在不是很常见,但在过去,它是),+ 0和-0有单独的值,因此8位数量的范围是-127到+127。


14
投票

在8位2的补码编码中,-128+128具有相同的表示:10000000。因此,硬件设计者面临一个明显的困境:如何解释位模式10000000。在形式上,它将以任何一种方式工作。如果他们决定将其解释为+128,则结果范围将为-127..+128。如果他们决定将其解释为-128,则结果范围将为-128..+127

在实际的2的补码表示中,选择后一种方法是因为它满足以下很好的约定:所有在高阶位中使用1的位模式代表负数。

值得注意的是,语言规范不要求二进制补码实现将100...0位模式视为任何有符号整数类型中的有效值。例如。允许实现将8位signed char限制为-127..+127范围,并将10000000视为无效位组合(陷阱表示)。


7
投票

我认为一个简单的方法来解释这个共同的灵魂是:

有点是值01,或2种可能性

2位保持两个组合或01四个可能的值:00011011

3位保存三种组合,总共有八种可能的值:000111

因此,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。地点:

10000000 = -128
...
11111111 = -1
00000000 = 0
...
01111111 = 127

3
投票
#include <limits.h>
#include <stdio.h>
...

printf("range of signed character is %i ... %i", CHAR_MIN, CHAR_MAX );

1
投票

如果你只考虑二进制补码作为算术模256,那么正负之间的截止是纯粹随意的。您也可以把它放在63 / -192,254 / -1,130 / -125或其他任何地方。但是,作为标准的有符号整数格式,通过惯例将二进制补码放在127 / -128。这个截止值有一个很大的好处:设置的高位直接对应于负数。

至于C语言,它将签名数字的格式留给实现,但只提供3种实现选择,所有选项都使用“符号位”:符号/幅度,补码和二进制补码。


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位数。

© www.soinside.com 2019 - 2024. All rights reserved.