【问题标题】:Range of signed char有符号字符的范围
【发布时间】:2011-04-23 08:35:17
【问题描述】:

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

【问题讨论】:

标签: c


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    如果您查看 chars 和 int 的范围,则在负数方面似乎有一个额外的数字。这是因为负数始终存储为其二进制的 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 位数字。

    【讨论】:

      【解决方案3】:
      #include <limits.h>
      #include <stdio.h>
      ...
      
      printf("range of signed character is %i ... %i", CHAR_MIN, CHAR_MAX );
      

      【讨论】:

        【解决方案4】:

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

        一个位是一个值01,或两种可能性

        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),负号也包括 -1 到 ... -128 的 128 个不同的值。哪里:

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

        【讨论】:

        • 您确实意识到,在二进制补码中,第一位不仅仅是符号位,对吧?如果是的话,你会有 -127 到 -0 作为有效值(因为如果它是符号位,你可能会有负 0)
        • @Mark,是的,我知道。但是,我试图坚持问题的界限。在大多数实际实现(C、Java 等)中,没有负 0。不过,您确实提出了一个有效点。
        • “最左边”位实际上是位。
        【解决方案5】:

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

        对于C语言,它把有符号数的格式留给实现,但只提供了3种实现选择,所有这些选择都使用“符号位”:符号/大小、一个补码和二进制补码。

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

          • @Chris Jester-Young 所以在 1 的补码编码中有 2 个零,即一个 +0 和一个 -0?
          • @Chris Jester-Young 还有一件事..是否需要相等的编号。 +ve & -ve 范围内的数字?以及为什么?
          • 嗯,在二进制补码和二进制补码中,最高位指定符号。去掉最高位,您会注意到有 7 位可用于正值,7 位可用于负值。
          • 另一个不常提及的好处是,在 2 的补码表示法中,除了检测符号溢出之外,没有额外的工作来处理有符号和无符号算术。
          • 还应该提到的是,C 标准支持使用 2 的补码、1 的补码和符号幅度的实现。
          猜你喜欢
          • 1970-01-01
          • 2012-07-07
          • 1970-01-01
          • 1970-01-01
          • 2016-02-06
          • 1970-01-01
          • 2011-11-23
          • 2013-10-04
          • 1970-01-01
          相关资源
          最近更新 更多