CSAPP 简记:#2第二章:Byte

第二章学习起来还是并不简单,书上公式和推导很多,所以在数学上感觉有些考验敏感度

1.进制

给出一个表。在这里插入图片描述
一个字节由8位组成。每台计算机都有一个字长,指明指针类型数据的标称大小,指针类型能表示多大的地址值决定了虚拟地址空间的最大大小,所以对于一个字长为32位的机器,虚拟地址范围为0~(2^32)-1,空间为4GB。对于64位机器,空间可达16EB。

|C声明 | 字节数(32) | 字节数(64)|
|–|–|–|–|–|
|char | 1 |1 |
|short | 2 | 2|
| int |4 | 4 |
|long |4 |8 |
|float | 4 | 4|
| double | 8 |8 |
| char *| 4 | 8|

2.数据在内存中的形式

在这里插入图片描述
排列表示一个对象的字节有两个通用的规则,即大端法和小端法。
小端法则是最低有效字节在最前面,大端法最高有效字节在最前面
大多数IBM兼容机都只用小端模式
在这里插入图片描述
可用如下代码查看数据在内存中的表示

#include <stdio.h>

typedef unsigned char *byte_pointer;
void show_bytes(pointer start, size_t len) {
	size_t i;
	for (i = 0; i < len; i++)
		printf("%p\t0x%.2x\n", start + i, start[i]);
	printf("\n");
}
void show_int(int x)
{
	show_bytes((byte_pointer)&x, sizeof(int));
}
void show_float(float x)
{
	show_bytes((byte_pointer)&x, sizeof(float));
}
void show_pointer(void *x)
{
	show_bytes((byte_pointer) &x, sizeof(void *));
}

布尔运算:
与 And:A=1 且 B=1 时,A&B = 1
或 Or:A=1 或 B=1 时,A|B = 1
非 Not:A=1 时,~A=0;A=0 时,~A=1
异或 Exclusive-Or(Xor):A=1 或 B=1 时,A^B = 1;A=1 且 B=1 时,A^B = 0
对应与集合运算则是交集、并集、差集和补集,假设集合 A 是 {0, 3, 5, 6},集合 B 是 {0, 2, 4, 6},全集为 {0, 1, 2, 3, 4, 5, 6, 7 } 那么:

& 交集 Intersection {0, 6}
| 并集 Union {0, 2, 3, 4, 5, 6}
^ 差集 Symmetric difference {2, 3, 4, 5}
~ 补集 Complement {1, 3, 5, 7}

3.整型

分为有符号数和无符号数:
在这里插入图片描述
简单地说二进制转无符号数(B2U)就是这个二进制本身所表示的,而二进制转有符号数(B2T)也称为补码表示,最高位是符号位。正数无符号数和有符号数表示相同。

在这里插入图片描述

极值:字长为w

在这里插入图片描述
字长为16的情况下
在这里插入图片描述

类型转换

无符号数和有符号数的转换(U2T\T2U) 在这里插入图片描述
当一个w位的位向量向量表示无符号数(U)和相同的位向量表示补码(T)在十进制下发现有以下关系:
U-T=2^w

在C语言中,默认的整型是有符号的,如果想要无符号数可以在数字后加U
如:

	int a=123;
	unsigned int b=321U;

如果一个表达式既含有无符号数和有符号数,将会被隐式转换为无符号数计算
在这里插入图片描述
当较小的类型转换到较大类型:
有符号:补符号位
无符号:补0
当较大类型转换到较小类型:
无符号:x mod 2^k(截断到k位)
有符号:先转到无符号如上操作再转到补码

运算与溢出
对于无符号数加法,如果两个 w 位的数字相加,结果是 w+1 位的话,那么就会丢弃掉最高位,实际上是做了一个 mod 操作(公式为 s=UAdd(u,v)=u+v mod 2^w)
对于有符号的加法,操作过程和无符号加法一样,只是解释的时候会有不同,因此会得到正溢出和负溢出两种。正溢出就是数值太大把原来为 0 的符号位修改成了 1,反而成了负数;负溢出是数值太小,把原来为 1 的符号位修改成了 0,反而成了正数。
对于乘法来说,值的范围会大很多,这里分情况讨论一下,假设两个乘数是 x,y 并且都是 w 位的
在这里插入图片描述
计算的无符号乘法的时候,会忽略最高的 w 位,相当于 UMult(u,v)=u⋅v mod 2^w

乘以常数

  1. 与2的幂相乘的无符号乘法和有符号乘法一样,x*2^k 在C表达式中为: x<<k

  2. 乘法指令相当慢,许多C语言编译器试图用移位和加减运算加快运算:
    形式A(一般更快)·x*6==(x<<3)-(x<<1) \\x*(8-2)

    形式B :x*6==(x<<2)+x(x<<1) \\x*4+x*2

除以2的幂
整数除法总是舍入到0,向下舍入一个正值,向上舍入一个负值。对于舍入:3.14 ≈4 (向上舍入),3.14≈3(向下舍入),-3.14 ≈-3(向上舍入)-3.14 ≈-4(向下舍入)

无符号逻辑右移,有符号算术右移

  • 无符号数:x/2^k ≈ x>>k(向下舍入)
  • 有符号数:x/2^k ≈ x>>k(向下舍入)(正值)
    x/2^k ≈ (x+(1<<k)-1)>>k (向上舍入) (负值)
    解释:在移位之前偏置了这个值,来修正舍入.(书中P73)
    合为一个表达式为: (x<0?x+(1+ k) - 1: x)>>k

4.浮点数

二进制小数

在这里插入图片描述

IEEE浮点数表示

在这里插入图片描述

  1. 符号(sign) s决定正负性, 对于0的符号位解释做特殊处理
  2. 阶码(exponent) E的作用是对浮点数加权,权重是2的E次幂
  3. 尾数(significand) M是一个二进制小数,它的范围是 1−2-ϵ

浮点数的位表示被划分为三个字段,分别对这些值进行编码:

  1. 一个单独的符号位直接编码成符号s
  2. k位的阶码字段exp 编码成阶码E
  3. n位小数字段frac 编码成尾数M
    在这里插入图片描述

此处引入书中表格,感受一下
在这里插入图片描述

试着将一个整数值转换成IEEE浮点表示的对理解浮点表示很有用:

  1. 将整数化为二进制表示
    如:12345=[11000000111001] 转成float
  2. 构造尾数
    将二进制小数点左移十三位 [11000000111001] =1.1000000111001 * 2^13
    取小数点后[1000000111001]补0到23位即 [10000001110010000000000]构成尾数M
  3. 构造阶码
    求偏置量(Bias), 在float中,exp有8位(k=8),E=exp-8, 由上可知E=13,Bias=2^8-1=127,所以exp为13+127=140,二进制表示为[10001100],
  4. 添符号
    12345为正,符号位为0
    综上12345.0 的float位表示为[0][10001100][10000001110010000000000]
舍入

对于浮点数的加法和乘法来说,我们可以先计算出准确值,然后转换到合适的精度。在这个过程中,既可能会溢出,也可能需要舍入来满足 frac 的精度。

向偶数舍入是默认方式
在这里插入图片描述

浮点数加法

在这里插入图片描述

浮点数乘法

在这里插入图片描述

C语言中的浮点数强制转换
  • int 转换成 float不会溢出可能被舍入
  • intfloat 转换成 double,可以保留精确的数值
  • double 转换成 float,值可能溢出成无穷,还可能被舍入
  • float 或者 double 转换成 int 值将会向零舍入
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值