深入理解计算机系统 第二章信息的表示和存储、

引言:

这一章我们研究在计算机上如何表示数据和其他类型数据的基本属性,以及计算机对这些数据执行操作的属性。在整数运算中,重点描述无符号数和数的补码所表示的特性;而对于IEEE标准的浮点型数据,一是它是如何表示数据的,二是浮点运算的数学形式。

三种常见的数据类型:整数分为无符号数和有符号数。无符号数,表示大于或者等于零的数,基于传统的二进制表示法;有符号数表示正数或负数,通常用补码来表示,浮点数多为小数类型的值。
现代计算机信息的存储和表示通过二值信号0和1来表示,最小的单位为位,bit。单个的位并没有什么意义,但是将多个位按照一定的顺序连接起来,就能够表示有限集合的元素。 

2.1信息存储,主要讲计算机如何存储二进制的数据,例如小端法和大端法这两种存储方式,同时还讲了一些布尔代数运算的基础,这就是我们熟悉的位运算和位移运算(Bitwise>
> & Bit Shift)以及逻辑运算。
> 2.2整数表示,主要说明有符号数和无符号数那些实现原理,例如有符号数会涉及到补码(Two’s Complement)处理。
>  2.3整数运算,则具体描述计算机如何给二进制数据做加减乘除运算,这里面还会继续分别讲解有符号数和无符号数的处理。
>  2.4浮点数,则单独地讲解计算机如何表示有小数点的数据,并如何做运算,但最重要的是浮点数精度限制问题的讲解。


 2.1 信息存储

计算机中可寻址的最小地址单元为字节,存储器的每个字节都由一个唯一的数字来标识,称为它的地址,所有可能地址的集合称为虚拟地址空间,包括随机访问存储器,闪存,内盘存储器等。

  • 十六进制表示

  十六进制数字:0 – F,例子:173A4C

 二进制数字:0 – 1,例子:0001 0111 0011 1010 0100 1100

 相互转换:十进制→ 十六进制:Mod(10,16)(倒序排列)

  • 字数据大小  

  字长决定的最重要的系统参数就是虚拟地址空间的最大大小。对于一个字长为ω位的机器而言,虚拟地址的范围就是0 ~ 2^ω - 1,程序最多访问2^ω个字节。

  • 寻址和字节顺序:

    多字节对象被存储为连续的字节序列,对象的地址为所用字节最小的地址。

    最低有效字节在最前面的方式,称为小端法。
    最高有效字节在最前面的方式,称为大端法。

  • 字符串表示:    

               每个字符用某个标准编码来表示,常见的为ASCII字符码。

  • 布尔运算

              ~非,&与,|或,^异或,位运算。

  • 逻辑运算

          逻辑运算认为所有非0参数表示TRUE,0表示FALSE。对应OR(||)、AND(&&)和NOT(!)。如果第一个参数求值就能确定表达式的结果,那么逻辑运算符就不会对第二个参数求值。    

  • 位级运算

       左移,x<<k,丢弃最高的k位,右端补k个零。右移分为逻辑右移和算术右移。逻辑右移在左端补0,算术右移在左端补最高位,在有符号的整数(最高位为1)移位时有区别。编译器默认为算术右移。当一次移位的k大于数的位数w时,C语言标准是移动k%w。

 2.2 整数表示

  • 整数分为无符号数和有符号数。

无符号数,表示大于或者等于零的数,基于传统的二进制表示法,如3表示为0011;

有符号数表示正数或负数,通常用补码来表示,有符号整数用补码编码,最高位为符号位,1表示负数,0为非负。负数的补码为原码的反码加1,正数的补码为本身。补码表示的范围,以4位为例,1000表示最小(-8),最大为0111(7),1111表示-1,0000表示0。

  • 有符号数和无符号数之间的转换

C语言允许在各种不同的数字数据类型之间做强制转换。

强制类型转换的结果保持位值不变,只是改变了解释这些位的方式。

执行一个运算的时候,如果它的一个运算数是有符号的而另一个是无符号的,那么C语言会隐式的将有符号数强制类型转换为无符号数,并假设两个数都是非负的,来执行运算。

  • 扩展一个数字的位表示

要将一个无符号数转换为一个更大的数据类型,只需要简单的在表示的开头添加0,这种运算被称为零扩展。

要将一个补码数字转换为一个更大的数据类型,可以执行一个符号扩展,在表示中添加最高有效位的值

 2.3. 整数运算

无符号加法:溢出直接去除高位。   
有符号加法:当做无符号数进行加法,溢出直接截断。
有符号的非:-x=~x+1,即等于按位取反再加1.
有符号数的乘法:x*y=(x的补码*y的补码)的补码
整数乘以常数:用移位和加法以及减小来代替乘法,无论x是无符号的还是有符号的,其计算结果一致。
整数除以常数:思路与乘法一致。有符号整数移位在小于0时会出现问题,当x<0时,x>>k的结果是x/(2^k)的向下取整,例如-12340>>4结果为-772,然而-12340/16应该是-771,这时C语言对其进行修改:(x<0?x+(1<<k)-1:x)>>k在x<0的情况下,加上(1<<k)-1的偏置量。

 2.4. 浮点数

符号位s:复数s=1,正数s=0

尾数M:是一个二进制小数

阶码E:对浮点数加权,权重为2,可以为负数

规格化的值

解码字段被解释为偏置形式表示的有符号整数。阶码的值是E = e - Bias,其中e是无符号数,而Bias是一个等于2^(k-1) - 1的偏置值。

小数子段frac被解释为描述小数值f,其中0 ≤ f < 1,二进制小数在最高有效为的左边。尾数定义为M = 1 + f。这种方式也叫做隐含的以1开头的表示。

非规格化的值

阶码值是E = 1 - Bias,而尾数的值是M = f,也就是小数字段的值,不包含隐含的开头的1。

非规格化数的另外一个功能是表示那些非常接近于0.0的数。它们提供了一种属性,称为逐渐溢出,其中,可能的数值分布均匀的接近于0.0。

浮点数的舍入: 默认为向偶数舍入法。

在C语言中,有两种浮点数float和double,舍入方法为向偶数舍入,

 整数和浮点数之间转换规则:
int转float不会溢出,可能被舍入。
double转float有可能溢出,可能被舍入。
float或double转int会向0舍入,例如1.9转为1,-1.9转为-1.可能溢出。
  

猜你喜欢

转载自blog.csdn.net/weixin_41792162/article/details/83591007