深入理解计算机系统----读书笔记
第二部分
信息的表示和处理
信息存储:
二进制(0101001), 八进制,十六进制(0x32FD)
字(word size)指明整数和指针数据的标称大小(normal size),对于w位的机器而言,虚拟地址范围0-2w-1,
如32位机器最大寻址为4GB,无符号整数表示0-42亿
数据大小 根据数据类型(int float bool等)
寻址和字节顺序 大端小端的问题(两种表示方法,在网络通讯的时候可能会产生问题,需要注意)
大端:最高有效位字节在前面
小端:最低有效位字节在前面
下图所示为小端表示机器显示结果(-12345的补码表示 0xCFC7)
布尔代数和布尔环
当考虑长度为w的位向量上的^,&和~运算时,会得到一种不同的数学形式,我们称之为布尔环( Boolean ring)
布尔环与整数运算有很多相同的属性。 如 整数运算的一个属性是每个值x都有一个加法逆元(additive inverse)-x
使得x+(-x) = 0。 布尔环的的“加法”是^(异或),即 a^a = 0;
因此 (a^b)^a= b 固有一下的代码:
void inplace_swap(int* x, int* y){ *y = *x ^ *y; // x =x , y = x ^ y *x = *x ^ *y; //x = x ^(x^y) = y, y = x ^ y *y = *x ^ *y; //y = y ^ (x ^ y) = x , }
以下代码可能会出现的问题:数组个数为奇数时,中间一位的数字变为0,奇数时正常逆序
void reverse_array(int a[],int cnt){ int first, last; for(first = 0,last = cnt - 1; first <= last; first++,last--) inplace_swap(&a[first],&a[last]); }
原因: 因为奇数时中间一位 调用inplace_swap()函数,a^a = 0;
修改方法: 1、在inplace_swap()前加上 if( first != last)判断, (ps: 后来看答案是 first< last,这种改法更合理)
2、修改inplace_swap()函数
C语言中的移位运算:
逻辑右移:在左端补k个0
算术右移:在左端补k个最高有效位的值(最有符号数据的运算非常有用)
小结: 无符号数逻辑右移和算术右移的位表示是一样的,
有符号数则不一样(有符号数采用补码表示),几乎所有的编译器/机器组合都对有符号数采用算术右移,程序员都 假设是机器会使用算术右移。
ps: 左移 =* 2n 右移 =/2n
移位运算优先级较低,低于加减 如果不清楚就增加括号, 如 1 << 2 + 3 << 4 实际意义: 1 << 5 << 4
有符号数与无符号数之间的转换:
Ps: 一般机器有符号数都用补码表示(但不是标准和原则)
要点:
1、C语言运行无符号数和有符号数转换,转换的原则是位表示保持不变
2、将无符号数扩展成更大的数据类型,在表示的开头加0,称为零扩展
3、将一个数的补码转换为一个更大的数据类型可以执行符号扩展,添加最高有效位的值的副本
//数据转换 扩展 short sx = -12345; unsigned short usx = sx; //53191 int x = sx; unsigned int ux = usx; printf("sx = %d\t",sx); show_bytes((byte_pointer)&sx,sizeof(short)); printf("usx = %u\t",usx); show_bytes((byte_pointer)&usx,sizeof(unsigned short)); printf("x = %d\t",x); show_bytes((byte_pointer)&x,sizeof(int)); printf("ux = %u\t",ux); show_bytes((byte_pointer)&ux,sizeof(unsigned));
结果如下: