C语言 1字节signed char的范围为什么是-128~127?

参考

1. 关于 -128 ,+128,-0,+0,-1 的反码补码 | 博客园

2. 八位二进制数为什么表示范围(-128~~+127)理解 | 博客园

 

无符号单字节范围

无符号单字节unsigned char位宽是8bit,范围[0, 1111 1111b],也就是[0, 255]。

 

有符号单字节范围

有符号单字节signed char位宽也是8bit,绝对值范围也是[0, 1111 1111b],不过最高位表示符号位,能表示的范围是多少呢?

不得不考虑一个特殊情况,0加符号位可表示+0,-0。而在早期计算机存储不够时,用2个不同的补码(±0)表示数学上的同一个0,是一种浪费,故规定-0表示为-128。

这样,[-127, 127](补码:[1000 0001b, 0111 1111b])就没有争议。

我们知道,

-128 = -127 - 1,那么,补码=1000 0001b - 1b = 1000 0000b ,最高位1,符号位未变;

128 = 127 + 1,那么,有两种情况

1)反码+1到补码符号位改变,补码=0111 1111b + 1b = 1000 0000b,最高位1,与-128补码相同。

2)反码+1到补码符号位不可变,补码=0111 1111b + 1b = 0000 0000b, 最高位为0,与+0补码相同。 (不符合溢出特点,因为+0不是最小的数,最大的数溢出后一般成为最小的数,舍)

由此,+128(若存在)及-128的补码,和-0原码是一样的。

 

那么,-128在计算机中实际上是如何用单字节存储的?

下面做实验验证,思路:用单字节signed char存储,然后直接debug查看存储的二进制值。

(调试环境:IDE Eclipse Photon,编译器:Cygwin GCC)

#include <stdio.h>

int main()
{
	signed char a = -128;
	signed char a2= -127;
	signed char a3 = 128;

	int na = sizeof(a);
	int na2 = sizeof(a2);
	int na3 = sizeof(a2);

	printf("a=%d , size=%d\n", a, na);
	printf("a2=%d , size=%d\n", a2, na2);
	printf("a3=%d , size=%d\n", a3, na3);

	a --;
	a2 --;
	a3 ++;
	printf("a=%d , size=%d\n", a, na);
	printf("a2=%d , size=%d\n", a2, na2);
	printf("a3=%d , size=%d\n", a3, na3);
	return 0;
}

 

可以发现,

a=-128 (Decimal)= 1000 0000 (Binary)

a=-127 (Decimal)= 1000 0001 (Binary)

a=+128 (Decimal),但计算机存储值=-128(Decimal)=1000 0000 (Binary)

 

 a, a2, a3自减1后,

a = 0111 1111(Binary) = 127 (Decimal)

a2 = 1000 0000(Binary) = -128(Decimal)

a3 = -127(Decimal)

 

对应Console输出

 

小结

1. 计算机中,C语言有符号单字节表示范围[-128, 127]

2. 无法直接存储128,会转换为-128

 

posted @ 2018-10-20 21:09  明明1109  阅读(2113)  评论(0编辑  收藏  举报