【C语言学习记录2】有符号与无符号

有符号数的表示法

数据类型的最高位用于标识数据的符号。

- 最高位为1,标识这个数为负数;

- 最高位为0,标识这个数为正数;

计算机内部用补码标识有符号数。

-正数的补码为正数本身;

-负数的补码为负数的绝对值各位取反后加1;

(负数的补码,符号位不取反)

为什么计算机中负数要用补码来表示么?

因为这样可以将减法运算化为加法运算处理。其次,若没有补码,则会有+0和-0表示两个0,用补码表示时,是一样的。这也恰恰说明,补码是唯一的。

扫描二维码关注公众号,回复: 6753676 查看本文章

无符号16数最大65535,有符号数32767(2的15次幂减一),最小有符号为-32768。

如果以最高位为符号位,二进制原码最大为0111111111111111=2的15次方减1=32767

最小为1111111111111111=-2的15次方减1=-32767

此时0有两种表示方法,即正0和负0:

0000000000000000=1000000000000000=0

所以,二进制原码表示时,范围是-32767~-0和0~32767,因为有两个零的存在,所以不同的数值个数一共只有2的16次方减1个,比16位二进制能够提供的2的16次方个编码少1个。

但是计算机中采用二进制补码存储数据,即正数编码不变,从0000000000000000到0111111111111111依旧表示0到32767,而负数需要把除符号位以后的部分取反加1,即-32767的补码为1000000000000001。

到此,再来看原码的正0和负0:0000000000000000和1000000000000000,补码表示中,前者的补码还是0000000000000000,后者经过非符号位取反加1后,同样变成了0000000000000000,也就是正0和负0在补码系统中的编码是一样的。但是,我们知道,16位二进制数可以表示2的16次方个编码,而在补码中零的编码只有一个,也就是补码中会比原码多一个编码出来,这个编码就是1000000000000000,因为任何一个原码都不可能在转成补码时变成1000000000000000。所以,人为规定1000000000000000这个补码编码为-32768。

所以,补码系统中,范围是-23768~32767。

实际上,二进制的最小数确实是 1111111111111111,只是二进制补码的最小值才是1000000000000000,而补码的1111111111111111 是二进制值的-1。

无符号数的表示法

在计算机内部用原码表示无符号数。(所有的无符号数最小的是0,最大的是根据占内存大小决定的)

- 无符号数默认为正数;

- 无符号数没有符号位;

对于固定长度的无符号数:

- MAX_VALUE + 1 => MIN_VALUE

- MIN_VALUE - 1 => MAX_VALUE

signed和unsigned

C语言中变量默认为有符号的类型;

unsigned关键字声明变量为无符号类型;

注意:

       C语言中只有整数类型能够声明unsigned变量。(浮点数不可以)

程序分析1:(有符号数碰上无符号数)

运行结果输出为i+j > 0。

解释:

       当有符号数遇见无符号数并进行运算时,有符号数被变为无符号数。

程序分析2:(错误的使用了unsigned)

运行结果:程序不停的运行。

解释:i被声明为无符号数,无符号数最小为0,故i >= 0 是一定成立的。当从0减1,变成四个字节的最大值。

小结:

1)有符号数用补码表示;

- 最高位为1,标识这个数为负数;

- 最高位为0,标识这个数为正数;

2)无符号数用原码表示;

- 无符号数只能用于表示正数;

- 无符号数没有符号位;

3)unsigned只能修饰整数类型的变量;

       - 当无符号数遇上有符号数混合运算时,会将有符号数转换为无符号数后再进行运算,结果为无符号数。

猜你喜欢

转载自blog.csdn.net/haibing_x/article/details/94411238