计算机系统——信息的表示和处理
信息的表示和处理
三种最重要的数字表示:
无符号(unsigned)编码基于传统的二进制表示法,表示大于或等于零的数字。
补码(two’ s-complement)编码是表示有符号整数的最常见的方式,有符号整数就是可以为正或者为负的数字。
浮点数(floating-point)编码是表示实数的科学记数法的以2为基数的版本。
计算机的表示法是用有限数量的位来对一个数字编码,因此,当结果太大以至不能表示时,某些运算就会溢出(overflow)。
信息存储
大多数计算机使用8位的块,或者字节(byte),作为最小的可寻址的内存单位,而不是访问内存中单独的位。
机器级程序将内存视为一个非常大的字节数组,称为虚拟内存(virtual memory)。
内存的每个字节都由一个唯一的数字来标识,称为它的地址(address),所有可能地址的集合就称为虚拟地址空间(virtual address space )。
C语言中指针的作用
指针是C语言的一个重要特性。
它提供了引用数据结构(包括数组)的元素的机制。
指针的两个方面: 值和类型。
它的值表示某个对象的位置,而它的类型表示那个位置上所存储对象的类型(比如整数或者浮点数)。
十六进制表示法
一个字节由8位组成。
在C语言中,以0x或0X开头的数字常量被认为是十六进制的值。
字符 ‘A’ ~ ‘F’既可以是大写,也可以是小写。
字数据大小
每台计算机都有一个字长(word size),指明指针数据的标称大小(nominal size)。
字长决定的最重要的系统参数就是虚拟地址空间的最大大小。
整数或者为有符号的,即可以表示负数、零和正数;
或者为无符号的即只能表示非负数。
C的数据类型char表示一个单独的字节。
大多数机器支持两种不同的浮点数格式:
单精度(在C中声明为float)和双精度(在C中声明为double)。
这两种格式分辨使用4字节和8字节。
寻址和字节顺序
对于跨越多字节的程序对象,我们必须建立两个规则:
这个对象的地址是什么,以及在内存中如何排列这些字节。
排列表示一个对象的字节有两个通用的规则:
大端法:最高有效字节在前面
小端法:最高有效字节在后面
例:
假设变量x的类型为int ,位于地址 0x100处,它的示例进制值为0x01234567。
地址范围0x100~0x103的字节顺序依赖于机器的类型:
表示字符串
C语言中字符串被编码为一个以null (其值为0)字符结尾的字符数组
每个字符都由某个标准编码来表示,最常见的是ASCII字符码。
表示代码
指令编码是不同的。
不同的机器类型使用不同的且不兼容的指令和编码方式,即使是完全一样的进程,运行在不同的操作系统上也会有不同的编码规则,因此二进制代码是不兼容的。
布尔代数
布尔代数: 通过将逻辑值TRUE(真)和FALSE(假)编码为二进制1和0,能够设计出一种代数,以研究逻辑推理的基本原则。
最简单的布尔代数是在二元集合{0,1}基础上的定义。
C语言中的位级运算
C语言的一个很有用的特性就是它支持按位布尔运算。
| 就是OR(或)
& 就是AND(和)
~ 就是NOT(取反)
^ 就是EXCLUSIVE-OR(异或)
对char数据类型表达式求值的例子:
位级运算的一个常见用法就是实现掩码运算,这里掩码是一个位模式,表示从一个字中选出的位的集合。
C语言中的逻辑运算
C语言还提供了一组逻辑运算符:
|| OR
&& AND
! NOT
逻辑运算认为所有非零的参数都表示TRUE,而参数0表示FALSE。
返回1或者0,分别表示结果为TRUE或者FALSE。
示例:
逻辑运算符&&和|| 与它们对应的位级运算 & 和 | 之间的第二个重要的区别是:
如果对第一个参数求值就能确定表达式的结果,那么逻辑运算符就不会对第二个参数求值。
C语言中的移位运算
C语言还提供了一组移位运算,向左或者向右移动位模式。
整数表示
描述用位来编码整数的两种不同的方式:
一种只能表示非负数,而另一种能够表示非负数、零和正数。
整型数据类型
C 语言支持多种整型数据类型 ——表示有限范围的整数。
每种类型都能用关键字来指定大小, 这些关键字包括 char 、short 、long , 同时还可以指示被表示的数字是非负数(声明为 unsigned ) , 或者可能是 负数(默认)。
无符号数的编码
补码编码
有符号数和无符号数之间的转换
C语言允许在各种不同的数字数据类型之间做强制类型转换。
例如, 假设变量 x 声明为int , u 声明为 unsigned 。表达式 (unsigned ) x 会将 x 的值转换成一个无符号数值, 而(int) u 将 u 的值转换成一个有符号整数。
C语言中的有符号数和无符号数
C 语言支持所有整型数 据类型的有符号和无符号运算。
尽管C 语言标准没有指定有符号数要采用某种表示, 但是几乎所有的机器都使用补码。通 常, 大多数数字都默认为是有符号的。
例如, 当声明一个像 12345 或者 Ox1A2B 这样的常量时, 这个值就被认为是有符号的。要创建一个无符号常量,必 须加上后缀字符 ’ u’ 或者 ’ u’ , 例如, 123450 或者 Ox1A2Bu。
扩展一个数字的位表示
一个常见的运算是在不同字长的整数之间转换,同时又保持数值不变。当然,当目标数据类型太小以至于不能表示想要的值时,这根本就是不可能的。然而,从一个较小的数据类型转换到一个较大的类型, 应该总是可能的 。
要将一个无符号数转换为一个更 大的数据类型, 我们只要简单地在表示的 开头添加 0。这种运算 被称为零扩展 ( zero extension) , 表示原理如下:
要将一个补码数字转换为一 个更大的数据类型, 可以 执行一个符号扩展 ( sign exten-sion) , 在表示 中添加最高有效 位的值, 表示为如下原理。我们用蓝色标出符号位 来突出它在符号扩展中 的角色。
截断数字
整数运算
两个正数相加会得出一个负数,而比较表达式 x<y 和比较表达式 x- y<O 会产生不同的结果。
这些属性是由于计算机运算的有限性造成的。
无符号加法
算术运算溢出,是指完整的整数结果不能放到数据类型的字长限制中去。
补码加法
补码的非
无符号乘法
补码的乘法
乘以常数
对无符号数乘以2的幂,
相当于对无符号数左移k位,将结果按无符号解释。
对补码表示的有符号数乘以2的幂,
相当于对有符号数左移k位,将结果按补码解释。
除以2的幂
浮点数
IEEE浮点数
对32位浮点数,
s占据最高1位
E占据次高8位
M占据低23位
对64位浮点数,
s占据最高1位
E占据次高11位
M占据低52位
解释:设E部分长度为k,M部分长度为t
1.1. 当E中全部为二进制0时,
M=0.t个M部分二进制序列
1.2. 当E中全部为二进制1时,
当M部分不全为0时,表示NaN
当M部分全为0时,表示正无穷或者负无穷【取决于符号】
1.3. 当E中不是全为0或者1时,
M=1.t个M部分二进制序列
从int转成float,数字不会溢出,但可能被舍入。
从int或float转成double,可保留精确数值
从double换成float,可能溢出为正无穷,负无穷。可能被舍入。
从float或double转成int,可能会溢出。值将向0舍入。
学习参考资料:
《深入理解计算机系统》 第3版
https://blog.csdn.net/x13262608581/article/details/107291692