C和内存中的带符号字节表示

时间:2013-08-02 09:38:42

标签: c byte

我得到的东西是:

C中的signed char以8位表示:00000000

  • 0是0000 0000 => 0
  • 1是0000 0001 => 1
  • ...
  • 127是0111 1111 => 127

所以我认为第8位是符号位。 所以我想:

  • 128是1000 0000 => 0
  • 129是1000 0001 => -1

但不!

试试这个:

int main(int argc, const char *argv[])
{
    int i;
    for (i = 0; i < 256; i++) {
        printf("%3d = %d\n", i, (signed char)i);
    }
    return 0;
}

你得到:gcc -o tt tt.c ; ./tt | more

  • ...
  • 126 = 126
  • 127 = 127
  • 128 = -128
  • 129 = -127
  • 130 = -126
  • 254 = -2
  • 255 = -1

怎么来的?

5 个答案:

答案 0 :(得分:7)

这称为有符号整数的2的补码表示,用于所有整数类型。

这个想法是这样的:CPU中的加法器只是在溢出发生并且环绕时忽略,所以你实际上在计算模数环上。因此,如果从零中减去1,则得到

 00000000 = 0
-00000001 = 1
--------------
 11111111 = -1

等等。

这样,您的计算机可以在计算时忽略符号。对于乘法,这甚至是正确的,如本例中3和-2的乘法(为简洁起见,4位算术):

0011 * 1110
-----------
       0000
      0011
     0011
    0011
-----------
     101010
truncated to 4 bits: 1010

10100110的否定值,为6,因此结果应为-6。

只需要很少的点需要考虑签名,比如比较,划分和转换为更大的整数类型。比较相对简单,演员表的工作方式如下:

00000001 -> 0000000000000001
10000000 -> 0000000010000000 (unsigned extension 128 -> 128)
10000000 -> 1111111110000000 (sign extension, the sign bit is copied into all new bits, preserving the value of negative numbers -128 -> -128)

答案 1 :(得分:5)

这是因为8位2的补码编码。符号字符范围是-128到127.

EDIT1:对@Grijesh评论的回应

-128和+128具有相同的表示形式:10000000。因此,为了避免混淆并制定规则All bit-patterns with 1 in higher-order bit represent negative numbers,决定将其视为-128,其范围为-128到127而不是-127 .. + 128。

答案 2 :(得分:4)

在二进制补码中,最左边的位是负数,其他位是正数,所以

1000 0000

=&GT; -128

1000 0001

=&GT; -128 + 1 = -127

因此最大数字是0111 1111(127),最小数字是1000 0000(-128)

答案 3 :(得分:2)

您可以将signed datatypes视为时钟。它会在12小时后达到12点钟。 Char范围为-128+127。因此,当您根据我的时钟规则点击127时,下次点击将为-128

我建议你做一些二进制计算。

有关详细信息,请参阅http://en.wikipedia.org/wiki/Two%27s_complement

答案 4 :(得分:1)

在c char中,唯一的1字节内存分配意味着总共8位。 这是因为8位2的补码编码。符号字符范围是-128到127 因为你用过。

   printf("%3d = %d\n", i, (signed char)i);