深入理解计算机系统(第2章 信息的表示和处理①)
- 无符号(unsigned)编码
- 补码(two's-complement)编码
- 浮点数(floating-point)编码
整数的表示是精确的;浮点数的表示是近似的。
(3.14 + 1e20) - 1e20 = 0.0
3.14 + (1e20 - 1e20) = 3.14
2.1 信息存储
一些基础概念:
- 大多数计算机使用8位的块,或者字节(byte),作为最小的可寻址的内存单位。
- 机器级程序将内存视为一个非常大的字节数组,称为虚拟内存(virtual memory)。
- 内存的每个字节都由一个唯一的数字来标识,称为它的地址(address)。
- 所有可能地址的集合称为虚拟地址空间(virtual address space)。
- 每个程序对象(program object, 即程序数据、指令和控制信息)可以简单地视为一个字节块,而程序本身就是一个字节序列。
2.1.1 十六进制(hexadecimal, hex)表示法
为避免冗长的二进制表示以及更方便地与位模式进行互相转化,以16为基础来表示位模式。
在C语言中,以0x或0X开头的数字常量被认为是十六进制的值。
十六进制与二进制的转化:以二进制的小数点为分界点,向左(或向右)每四位取成一组,每一组代表一位十六进制数。
2.1.2 字数据大小
每台计算机都有一个字长(word size),指明指针数据的标称大小(nominal size)。
字长决定了虚拟地址空间的最大大小。对字长为
大多数64位机器能够运行为32位机器编译的程序(向后兼容)。
2.1.3 寻址和字节顺序
在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址。eg:&x = 0x01234567,则x(4字节)被存储在0x100、0x101、0x102和0x103位置。
存储方式:
- 大端法(big endian):最高有效字节在最前面的方式。(Mac OS、PowerPC、IBM、Sun、 TCP/IP网络数据流……)
- 小端法(little endian):最低有效字节在最前面的方式。(x86、Linux、iOS、Android……)
- 双端法(bi-endian):可以配置成作为大端或者小端的机器运行。(少数新的微处理器)
字节顺序可能出现问题的情况:
- 在不同类型的机器之间通过网络传送二进制数据。
- 阅读表示整数数据的字节序列。
- 编写规避正常的类型系统的程序。
2.1.4 表示字符串
在使用ASCII码作为字符码的任何系统上都将得到相同的结果,与字节顺序和字大小无关。
因而,文本数据比二进制数据具有更强的平台独立性。
2.1.5 表示代码
不同的机器类型使用不同的且不兼容的指令和编码方式。
二进制代码是不兼容的。二进制代码很少能在不同机器和操作系统组合之间移植。
2.1.6 布尔代数(Boolean algebra)简介
{0, 1}
2.1.7 C语言中的位级运算
&:位与
|:位或
~:位非
^:位异或
运算原则:按位进行布尔代数的运算。
可以仅使用位异或而不适用额外变量来实现数据交换
void inplace_swap( int *x, int *y ) { *x = *x ^ *y; *y = *x ^ *y; *x = *x ^ *y; }
2.1.8 C语言中的逻辑运算
&&:逻辑与
||:逻辑或
!:逻辑非
运算原则:所有非零的参数都表示TRUE,参数0表示FALSE。仅返回0或者1。
按位运算只有在参数被限制为0或者1的特殊情况下,才和与其对应的逻辑运算有相同的行为。
若逻辑与的第一个表达式为假,则机器不会再去检查第二个表达式的真假或合理性。(有下述例子)
2.1.9 C语言中的移位运算
逻辑右移——最左端空位填充0。
算术右移——根据最高位进行填充。
注意事项:
- 在实践中,几乎所有的编译器针对有符号数的右移都采用的是算术右移,大多数程序员也将这种情况视为默认。
- 移位
,当 大于等于变量位长 时,移位 mod 。 - 移位运算的优先级要低于加和减,操作符优先级问题经常容易导致结果出错,尽量多使用括号。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步