有符号型

有符号型

所谓的有符号型,就是指数的符号位可以取正负值。
有符号整型由两部分组成,符号位和数值位。符号位用来表示数值的正负,数值位用来表示数值的大小。

符号位

符号位有两种取值:

  • 0:表示数值为正数。
  • 1:表示数值为负数。

数值位

数值位用来表示数值的大小。

对于有符号整型,数值位的位数是固定的,具体取决于整型的位数。

对于有符号整型,数值位的取值范围是从-2^(n-1)~~2^(n-1)-1其中n是整型的位数。

例如,对于有符号整型 int8_t,它的数值位的取值范围是从-128~~127

负数在内存中的表示

对于有符号整型,负数在内存中是以补码形式存储的。

补码是一种二进制数的表示方法,它是将原码的符号位和数值位分别取反,并在符号位的右边加上一个1。这是一种简单的方式,我们也可以用其它的角度来推导。

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int main(void)
{
unsigned char a;
a = 0b11111111;//0b表示采用二进制表示,100000000表示十进制的256
a=a+1;
printf("%hhu \n", a);//输出a的值为0
//%hhu表示以无符号输出a的值,%hhu有字节限制为一字节(0-255),如果超出范围会自动截断(溢出)
return 0;
}


上图很清楚地展示了上述代码的执行过程。我们将通过这种原理来探讨负数在内存中的表示。
我们使用singed char来举例,(应为它是一个字节的有符号整型)

· 首先,对于无符号整型来说一个字节的取值范围是0到255,而对于有符号整型来说,一个字节的取值范围是-128~127。我们
可以发现可表达的总个数是相同的。这说明我们将256/2=128个数用来表示了负数。

· 其次,我们知道1+(-1)=0,那么通过上文的溢出例子可以知道,一字节内存中,00000001+11111111=100000000,但最高位溢出,实际得0。
根据相同原理我们可以推导出,-x=256-x(256=100000000)

· 最后,我们可以发现,最高位为论为1还是0,只要最高位不变其余7位说表达的数字个数相同,这就将正负数表达出来了,那么我们就可以通过这个最高位来判断符号。
即1表示负数,0表示正数。

·我们还可以发现一个有趣的现象,就是+0与-0和-128的问题,稍加思考就可得出结论,+0与-0(00000000)的最高位都应是0,而-128(10000000)的符号位应为1。