读书笔记Pt.4——《深入理解计算机系统》

读书笔记Pt.4——《深入理解计算机系统》,第1张

目录
    • 传统艺能😎
    • 数据大小😎
    • 寻址与字节顺序😎
    • 整数表示🤔
    • 无符号数的编码🤔
    • 补码编译🤔

传统艺能😎

小编是双非本科大一菜鸟不赘述,欢迎大佬指点江山(QQ:1319365055)
此前博客点我!点我!请搜索博主 【知晓天空之蓝】
乔乔的gitee代码库(打灰人 )欢迎访问,点我!

🎉🎉非科班转码社区诚邀您入驻🎉🎉
小伙伴们,打码路上一路向北,背后烟火,彼岸之前皆是疾苦
一个人的单打独斗不如一群人的砥砺前行
这是我和梦想合伙人组建的社区,诚邀各位有志之士的加入!!
社区用户好文均加精(“标兵”文章字数2000+加精,“达人”文章字数1500+加精)
直达: 社区链接点我

🎉🎉🎉倾力打造转码社区微信公众号,等你加入!🎉🎉🎉


数据大小😎

计算机和编译器支持多种不同数据类型,整型浮点数这些的,许多机器都有处理单个字节的指令,也有处理2,4,8字节的整数的指令。

C语言的 char 类型表示一个单独的字节,尽管 char 是字面上用于存储单个字符,但他也可以用来存储整数值。我在C语言入门就已经展示了不同数据类型分配的字节数:

随着64位机器的普及,程序移植到新机器上时,隐藏的对字长的依赖性就会显现出来称为错误,比如假设一个声明为 int 的程序被用来存储指针,在 32 位机器上可能是可行的,但在64位机器上就会完犊子。

寻址与字节顺序😎

对于跨越了多字节的程序,我们必须有对应的两套标准:对象地址和存储器中的排列方式。几乎所有机器上多字节都被存储为连续的字节序列,地址为所使用字节中最小地址,比如一个 int x 的地址为0x100,也就是&x的值为0x100,那么他的四个字节就被分配在了0x100,0x101,0x102,0x103的位置。

排列表示一个对象的字节有两个通用规则,不扯那些难懂的书面语,说白了就是我们之前学习的大小端模式。有的机器会选择从低有效字节到最高有效字节存储,有些则恰恰相反。最低有效字节位于前面的方式就是小端法,最高有效字节位于前面就是大端法。现在许多前沿的微处理器使用双端法,即可以自行配置作为大端或者小端使用。

大端和小端的起源其实是源自于《格列佛游记》中的鸡蛋问题,书中人民对于鸡蛋该从哪边剥变现的十分情绪化,现实中也和鸡蛋问题一样,字节顺序规划并没有技术上的原因。

虽然不同类型机器编译会得到相同结果,但是通过网络传输二进制数据时小端的数据发送到大端会反序,所有网络程序的代码必须遵循建立的标准其次,阅读字节序列时字节的顺序也很重要,比如我们从文件里摘出这个代码:

这是由反汇编产生的代码,反汇编器就是确定程序文件所表示的指令序列的工具,,我们只需要注意里面的16进制字节串 01 05 64 94 04 08,它是指令的字节级表示,这条指令将一个字长数据放到地址 0x8049464 的值上,取出后面4位字节(一个整型)反序得到 08 04 94 64,再去掉开头的0就是 0x8049464。

字节顺序变得可见的第三种情况就是编写规避正常的类型系统程序时。比如C语言里面我们可以使用强制类型转换来引用一个对象,而类型与实际定义不同,虽然大多数程序强烈不推荐这种技巧,但对于某些系统级编程是有用甚至必需的。

整数表示🤔

C语言支持多种整型数据类型——表示有限范围的整数


这里还给出了32位和64位机器的取值范围。每种类型都可以用关键字来指定大小,同时还可以指示对象是否为负如 unsigned,这些不同大小多少字节数会根据机器的字长和编译器有所不同,这里唯一一个和机器有关的大小指示符是 long,64位机器使用 8 个字节表示是 32位 4 个字节的两倍。

我值得注意的是这些取值范围并不是对称的,负数会比整数大1,这是如何表示负数会讲到的问题。C语言定义了每种数据必须能够表示的最小取值范围,而这些取值范围(正负数)是对称的。注意C和C++都支持有符号和无符号数而 JAVA 只支持有符号数

无符号数的编码🤔

因为符号和标注键盘实在扣不出来,这里就贴个图吧

上面 2^i 的条状表示来反映每个位的位置 i 每个位向量就等于值为1的位对应的长度之和,我们以 w = 4 的无符号数为例


考虑一下 w 位能表示的值的范围,最小值用位向量 [000……0]表示,最大位[111……1]表示,w = 4时,UMax = 2^4 -1 = 15,因此就会定义出一个最大值为 15 的映射。

无符号数的二进制表示是一个很重要的属性,每个介于0~(2^w) - 1的数都有唯一一个 w 位的值编码。比如十进制的 11,只有一个 4 位的表示:[1011],这个属性就是指函数是一个双射——每个长度为 w 的位向量都有一个唯一值与它对应,反过来每个介于0~(2^w) - 1的数都有唯一一个 w 位的位向量与它对应。

补码编译🤔

对于许多应用我们还希望能够表示负数值,常见的表示方式就是补码形式

在补码的定义中,将字的最高有效位解释为负权,他也可以函数表示:

我和用向左指的条表示符号位的负权重,因此位向量关联的数值可以由向左指的条相加决定,其实和上面无符号数编码是一样的:

作用原理也和无符号数是一样的,比如给出一个 w = 4 为例,TMin = B2T_4([1000]) = -2^3 = -8,而TMax = B2T_4([0111]) = 22+21+2^0 = 7。


那么关于这些数字,有几点需要注意:

  1. 补码范围不对称,|TMax|+1 = |TMin|,也就是说 TMin 没有与之对应的正数,这就造就了补码的一些特殊属性且容易造成一些细微错误。其原因因为一半的数符号位 1 表示负数,而一半的数符号位 0 表示非负数,抠掉 0 这个小特殊就会让 正数少一个。
  2. 最大的无符号数值刚好比补码最大值两倍大一点:UMax = 2*TMax + 1;补码中所有表示负数的位模式在无符号数里面全变成了正数。

C语言并没有规定要补码来表示有符号整数,但几乎所有机器都这么干了,因为我们希望代码具有最大可移植性,其次是许多程序的有符号数都假设用补码来表示。C语言库里面头文件定义了一组常量来限制机器中不同整型的取值范围,比如 INT_MAX,INT_MIN 和 UINT_MAX就描述了有符号和无符号整数的范围,一台机器 int 类型如果有 w 位 ,这些常量就对应了 TMax,TMin 和 UMax 的值。

今天就到这里吧,摸了家人们

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/755732.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-30
下一篇 2022-04-30

发表评论

登录后才能评论

评论列表(0条)

保存