《深入理解计算机系统》第二章:整数的表示

《深入理解计算机系统》第二章:整数的表示


前言

我将在本篇文章,详细回顾一下自己对整数的表示的理解。


一、64位机器上的数据类型

在这里插入图片描述
需要注意的是,在64位机器上,long类型8个字节,然而在32位机器上long只占4个字节。unsigned是无符号数,原则上恒大于等于0的数。是C语言的专属特性,其他语言均不支持无符号数。

二、无符号数的编码

2.1 表示和计算

在这里插入图片描述
使用B2U表示将二进制数表示成无符号数,举个例子如下:
在这里插入图片描述
CSAPP原书里面给出了一个图形的方式来表示无符号数:
在这里插入图片描述
如上图所示,二进制【x1,x2,x3,…】等于,所有位为1的进度条的长度相加得到的和。

2.2 UMax

UMax: 无符号数的最大值
在这里插入图片描述
无符号的最大值是,所有位全为1;十进制的最大值表示:2^n-1;其中n是字节数。

三、有符号数的编码

无符号数不需要符号位来表示一个数,这样对于无符号数是比较简单和高效的,但是不能用来标识有符号数。在计算机中有符号数的表示使用补码的形式。
关于为什么是补码,我觉得这个博客讲的还可以,因为有种种原因吧,补码可以直接用于数字的计算。

3.1 补码

正数的补码 == 正数本身
负数的补码 == 原码的基础上, 符号位不变,其余各位取反, 最后+1

使用一个向量来表示有符号数,它的计算公式如下所示:
在这里插入图片描述在这里插入图片描述
10000010 = -2^7 + 2 = -126,在比如下图所示:
在这里插入图片描述

关于符号位,要理解负权重的概念,不能简单的当作成一个符号位
需要注意的是-1在任何字节的补码表示下都是全1

3.2 TMax&TMin

TMax:有符号数的最大值
在这里插入图片描述

TMin: 有符号数的最小值
在这里插入图片描述

四、U2T&T2U 有无符号数的转换

转换规则
有符号位和无符号位之间的转换规则是:
1、位模式表示不变
2、需要重新解释
3、需要加减2^w
下面看一下公式的推导:
在这里插入图片描述
在这里插入图片描述
下面看一下CSAPP的图:
在这里插入图片描述
接下来看一个T2U的案例:
在这里插入图片描述

五、unsigned注意事项

在这里插入图片描述
C语言中,有符号数与无符号数的运算,会将有符号数转换成无符号数

5.1 注意1

,如下图的案例所示。
在这里插入图片描述
a = -1,但是当其与有符号数进行比较运算时,a的值会被转换成无符号数,x < 0时,T2U(x) = x + 2^w,也就是a会转成 -1 + 4 294 967 296 ==>4 294 967 295,而4 294 967 296是大于0的,所以会输出 -1 > 0 的结果。

5.2 注意2

下图所示的这种情况是因为 length - 1 应该等于 -1 ,但是在C语言中,无符号数与有符号数之间的运算,会将有符号数转换成无符号数,所以-1转成无符号数之后,就是无符号的最大数,但是数组的范围是有限的,当数组下标到达最大无符号数的时候,数组肯定会出现访问越界。
问题2

5.3 注意3

下面这个例子来自于南大的课件,同样当n = 0是,n - 1 会被转换成无符号的最大值,而无符号数i是天然小于等于UMax的,所以这里会出现死循环。
问题3

5.4 如果正确使用unsigned

在这里插入图片描述
大神提出的解决方法如上图所示,但是除非必要,尽量不使用unsigned,是避免出现这种问题的最直接方法。

六、Sign Extension 位扩展

在这里插入图片描述

6.1 位扩展的注意事项

1、无符号数的扩展,直接前面补0即可
2、有符号数的扩展,需要将无符号位进行扩展,比如下图所示:
在这里插入图片描述
有符号负数的扩展,前面补零;有符号负数的扩展前面补1。
正数的扩展没有什么好说的,比如byte类型的数7转成int类型,直接高位填充0即可。

00000111->00000000 00000000 00000000 00000111

负数的扩展,则是直接填充1

10000111(-121) -> 11111111 11111111 11111111 10000111

可以算一下上边负数的扩展是正确的。
注意:C++中负数不支持左移位,因为结果是不定的,比如:int c = (unsigned int)(a & b) << 1;具体看leetcode上剑指offer65题

6.2 有符号数扩展的数学证明

定义二进制转补码的函数B2T:
在这里插入图片描述
根据数学归纳法,要想证明(1)和(2)相等,可以最终归为证明B2T(w+k) == B2T(w+k-1)。
在这里插入图片描述
在这里插入图片描述
综上所述,当有符号数从一个较小的数据类型转成较大的数据类型时,进行符号位扩展可以保证数值不变。

七、Truncating Numbers 位截断

7.1 截断无符号数

当较大的数据类型转成较小的数据类型时,会发生位截断。比如下图所示,将int类型的53191,这个数字显然大于short所能表示的数字范围,就会发生截断,将高16位丢弃,保留低16位,造成了数值的变化。
在这里插入图片描述
截断的原理类似于取余操作,比如将123456对1000进行取余,即可保留后三位数字。
在这里插入图片描述

7.2 截断有符号数

有符号的数截断分为两步:
1、用无符号数的函数映射来解释底层的二进制位,然后使用无符号的截断方式对数值进行截断。
2、将第一步得到的无符号数转换成有符号数
经过上面两步,即可完成对有符号数的截断。
在这里插入图片描述


总结

整数的表示是计算机基础体系结构中十分重要的基础知识,作为一个程序员,掌握良好的计算机体系结构,是基本素养。其中对于有符号数与无符号的数的运算,是容易忽视的点,如果不仔细学习一下,当出现Bug时,可能都搞不清楚为什么。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值