[CSAPP笔记][第二章信息的表示和处理]

信息的表示和处理

2.1 信息存储

  • 机器级程序将存储器视为一个非常大的字节数组,称为虚拟存储器
  • 存储器的每个字节由一个唯一的数字表示,称为它的地址
  • 所有可能地址的集合称为虚拟地址空间

2.1.1 十六进制表示法

python 中十六进制的转变方法

a=15;
print(hex(a))

//print:0xf

2.1.2 字

  • 字长决定虚拟地址空间的最大大小
  • 32位的是4G(2^32)

2.1.3 数据大小

  • char *使用了机器的全字长

2.1.4 寻址和字节顺序

  • 小端法:大多数Intel兼容机规则(现在最为常用)

    • 高位放高地址
  • 大端法:IBM 和Sun Microsystems
    • 高位放低地址
  • printf(“%.2x “)解析

    摘自K&R《C程序设计语言》:

    点号,用语分隔字段宽度和精度

    表示精度的数。对于字符串,它指定打印的字符的最大个数;对于e、E或f转换,它指

    定打印的小数点后的数字位数;对于g或G转换,它指定打印的有效数字位数;对于整型数,它指定打印的数字位数(必要时可填充位0以达到要求的宽度)

2.1.5 表示字符串

  • 在使用ASCII码作为字符码的任何系统都会表示相同的结果,与字节顺序和字大小规则无关。因而,文本数据比二进制数据具有更强的平台独立性
  • Java使用Unicode 来表示字符串。对于C语言也有支持Unicode的程序库

2.1.6 表示代码

即使是相同的一段代码,在不同的机器类型使用不同,不兼容的指令,因此二进制代码是不兼容的。

2.1.7 布尔代数简介

很简单

  • 位向量常用于集合的表述(状态压缩常用)

2.1.8 C语言的位级运算

ACM玩的很多了,就不说了

2.1.9 C语言的逻辑运算

  • || && 惰性求值

2.1.10 C语言的移位运算

  • 逻辑右移

    • 往左边补k个0
  • 算术右移
    • 往左边补k个最高有效位的值
    • 对有符号运算有奇效

潜在问题

  • 对于无符号数据,右移必须是逻辑的。
  • 对于有符号数据,逻辑,算术都可以。
    • 几乎所有编译器对有符号使用算数右移
    • 许多程序员也假设使用算数右移
    • 可能会存在潜在的兼容性问题

2.2 整数表示

2.2.1 整数数据类型

  • 有符号
  • 无符号
  • 负数比正数大一(有一个-0被表示为最小的那个负数)

2.2.2 无符号数的编码

  • 性质:双射

2.2.3 补码编码

用这种方式理解补码,是一种新的不错的思路

  • 很容易算出范围。不用思考转成原码
  • 双射,规则没有特例,很容易看出0不能表示两种。

补码,反码

2.2.5 C语言中的有符号数和无符号数

  • 默认为有符号,如果需要无符号某尾+U,例:12345U

2.2.6 扩展一个数字的位表示

  • 对于一个无符号数转为更大的数据类型

    • 只需要简单地在表示的开头添加0,这种运算称为零扩展
  • 对于有符号的数,即补码
    • 进行符号扩展(sign extension),就是添加最高有效位的值
  • 对比逻辑右移,和算术右移

2.2.7 截断数字

  • 截断一个数到k位,即舍去w-k的高位。
  • 对于无符号数截断x它到k位的结果相当于
    • B2U([Xk-1,Xk-2,….x0])=B2U([Xw-1,Xw-2…x0]) mod 2^k
  • 对于有符号的数x。
    • 截断的时候还是当做无符号的数看
    • B2T([Xk-1,Xk-2,….x0])=U2T(B2U([Xw-1,Xw-2…x0]) mod 2^k

      )

建议

  • 在大多数情况下使用有符号整数

    • java中只支持有符号整数,>>算数右移,>>>才是逻辑右移

2.3 整数运算

2.3.1 无符号加法

  • x+y = (x+y) mod 2^k
  • 溢出会舍去
  • 阿贝尔群,群论。

2.3.2 补码加法

  • 大多数计算机使用同样的机器指令来执行有符号和无符号之和。

  • x(有符号+)y= U2T(T2U(x+y) mod 2^w)
      1. 先计算x+y
      1. 将x+y转换为无符号类型z。
      1. p=z mod 2^w
    • 附.(或者直接对x+y的二进制表示进行截断得到p)
      1. 将p用有符号类型表示
  • 正溢出,正常,负溢出。

2.3.3 补码的非

  • 因为正负区间的不一致
  • 所以最小的那个负数的相反数逆元还是最小的那个负数。
  • 对于任意整数x-x~x+1得到的结果完全一样。

2.3.4 无符号乘法

  • 只取低w位表示的值,其余截断

2.3.5 补码乘法

  • 对于无符号和补码乘法,乘法运算的位级表示都是一样的,是同一条指令。
  • 无符号和补码相乘出来的两个数的低W位 永远相等。证明见书。

2.3.6 乘常数

  • 因为乘法速度太慢,机器可能会用(加法,减法,移位)来代替乘法。

2.3.7 除以2的幂

  • 对于无符号类型或整数,直接右移不会有任何问题。
  • 对于负数,最后的值为-48.3,会舍入成 -49,而不是-48.
    • 解决方法是偏置
    • 原理:
    • C语言
      (x<0 ? (x+(1<<k)-1):x)>>k
      等价于x/pwr2k ,pwr2k=2^k
      

2.4 浮点数

之后看,现在先过别的。

时间: 2024-10-21 11:54:15

[CSAPP笔记][第二章信息的表示和处理]的相关文章

Git帮助文档阅读笔记----第二章-第五节---打标签

本节我们一起来学习如何列出所有可用的标签,如何新建标签,以及各种不同类型标签之间的差别. 列显已有的标签 直接运行 git tag 即可: 可以用特定的搜索模式列出符合条件的标签.在 Git 自身项目仓库中,有着超过 240 个标签,如果你只对 1.4.2 系列的版本感兴趣,可以运行下面的命令: $ git tag -l 'v1.4.2.*' v1.4.2.1 v1.4.2.2 v1.4.2.3 v1.4.2.4 新建标签 轻量级的(lightweight) 含附注的(annotated)(建议

Mysql Cookbook学习笔记第二章

1,使用python链接mysql + ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # -*- coding: utf-8 -*- # connect.py --连接到MySQL服务器 import sys import MySQLdb try:     conn = MySQLdb.connect(db = "cookbook",                            host = "localhost"

《深入理解Java虚拟机》读书笔记---第二章 Java内存区域与内存溢出异常

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来.这一章就是给大家介绍Java虚拟机内存的各个区域,讲解这些区域的作用,服务对象以及其中可能产生的问题. 1.运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 1.1程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型中里,字

Git帮助文档阅读笔记----第二章-第二节

查看提交历史 1.查看提交历史 git log 默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面 git log 有许多选项可以帮助你搜寻感兴趣的提交 1.  -p选项展开显示每次提交的内容差异 2.  -2显示最近的两次更新 该选项除了显示基本信息之外,还在附带了每次 commit 的变化.当进行代码审查,或者快速浏览某个搭档提交的 commit 的变化的时候,这个参数就非常有用了. 某些时候,单词层面的对比,比行层面的对比,更加容易观察.Git 提供了 

Git帮助文档阅读笔记----第二章-第四--节远程仓库的使用

管理这些远程仓库,以便推送或拉取数据 添加远程库 移除废弃的远程库 管理各式远程库分支 定义是否跟踪分支 查看当前的远程库 可以用 git remote 命令,它会列出每个远程库的简短名字 也可以加上 -v 选项(译注:此为 --verbose 的简写,取首字母),显示对应的克隆地址: 如果有多个远程仓库,此命令将全部列出.比如在我的 Grit 项目中,可以看到: 添加远程仓库 要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行 git remote add [shortname

Git帮助文档阅读笔记----第二章-第三节

撤消操作 1.修改最后一次提交 有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了.想要撤消刚才的提交操作,可以使用 --amend 选项重新提交: $ git commit --amend 直接运行此命令的话,相当于有机会重新编辑提交说明,但将要提交的文件快照和之前的一样. 如果刚才提交时忘了暂存某些修改,可以先补上暂存操作,然后再运行 --amend 提交 $ git commit -m 'initial commit' $ git add forgotten_file $ g

《Java并发变成实践》读书笔记---第二章 线程安全性

什么是线程安全性 要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的(Shared)和可变的(Mutable)状态的访问.从非正式的意义上来说,对象的状态是指存储在状态变量(例如实例或静态域)中的数据."共享"意味着变量可以由多个线程同时访问,而"可变"则意味着变量的值在其生命周期内可以发生变化.所以编写线程安全的代码更侧重于如何防止在数据上发生不受控的并发访问. 如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么程序就会出现错误

高项3.7日第一次课,第一章信息化基础知识与第二章信息系统服务管理梳理

第一章 信息化的基础知识 1.国家信息化体系要素: 主要包括6要素,信息技术应用(龙头).信息资源(关键).信息网络(必要手段).信息技术产业(基础).信息化人才(成功之本).信息化法规政策和规范(保障). 2.电子政务: 电子政务建设的指导原则: (1)统一规划,加强领导. (2)需求主导,突出重点. (3)统一规划,拉动产业. (4)统一标准,保障安全. 主要任务: (1)电子政务网络由政务内网和政务外网构成,两网之间物理隔离,政务外网与互联网之间逻辑隔离.政务内网主要是副省级以上政务部门的

《Linux Shell脚本攻略》 笔记 第二章:常用命令

<Linux Shell脚本攻略> 笔记 第二章:常用命令 1.cat cat -s //多个空白行压缩成一个 cat *.txt | tr -s '\n'   //移除空白行 cat -n //加行号 2.find 沿着文件层次结构向下遍历,匹配符合条件的文件,并执行相应的操作. eg: find ./ ! -name "*.txt" -print [[email protected] program_test]# find ./  -type f -name "