现代计算机存储和处理信息以二值信号表示,这些二进制数字称为位。计算机用几种不一样的二进制表示来编码数值。html
计算机将信息按位编码,一般组织成字节序列。用不一样的编码方式表示整数、实数 和 字符串。前端
不一样的计算机模型在编码数字和多字节数据中的字节排序时使用不一样的约定。git
c语言的设计能够包容多种不一样字长和数字编码的实现。大多数机器对整数使用补码编码,而对浮点数使用IEEE
浮点编码。程序员
在相同长度无符号和有符号整数之间进行强制类型转换时,大多数C语言实现遵循的原理则是底层的位模式不变。编程
在补码机器上,对于一个w位的值,这种行为是由函数T2UW
和U2TW
来描述的安全
强制类型转换来容许以种数据类型引用一个对象,而这种数据类型与建立这个对象时定义的数据类型不一样。大多数编程不推荐这种编码技巧,可是对系统级编译程序是很是有用的,甚至是必须的,可是会出现许多程序员没法预计的结果,经常致使程序错误函数
因为编码长度有限,与传统整数和实数相比,计算机运算具备彻底不一样的属性。当超出表示范围时,有限长度可以引发数值溢出。例如:当浮点数很是接近于0.0,从而转换成0时,也会下溢出。学习
在移位运算中,注意区分逻辑右移和算数右移。逻辑右移在左端补k个零,算数右移在左端补k个最高位有效值。左移就是向左移动k位,丢弃最高的k位,并在右端补k个零优化
c语言实现的有限整数运算和真实的整数运算相比有一些特殊属性。例如:因为溢出,200300400*500会得出结果-884 901 888(使用32位来表示数据类型int),可是无符号数和补码的运算都知足整数运算的结合律、交换律和分配律,能够容许编译器作不少的优化。编码
浮点表示经过数字编码为x*2^y
的形式近似表示实数
注意由于浮点数只有有限的范围和精度,不会遵照广泛的算数属性。
关于大端法和小端法
最开始在理解二者定义的时候都没有问题,区分两者的不一样在于有效字节的排列高低。最低有效字节在最前面成为小端法,最高有效字节在最前端称为大端法。
可是书上关于Ox01234567的例子为何高位字节的十六进制是Ox01 低位十六进制是Ox67?
后来经过作课后习题关于Ox87654321的例子明白了,由于每一个十六进制的数字,在地址排列中有两个通用规则。考虑一个w位的数,位表示为[Xw-1,Xw-2,...,X1,X0]
其中Xw-1
是最高位,X0
是最低位.这样一来就能够明白高位字节是Ox01,低位字节是Ox67,这样问题就顺利解决了。
关于表示字符串
经过之前的学习也知道是由一张ASCII字符码表,可是对于使用使用ASCII做为字符码的任何系统上会获得相同结果,与字节顺序和字大小规则无关并不太理解。
在虚拟机下使用man ascii
获得一张ASCII表,并用书上的例子
const cahr *s ="abcdef" show_bytes( (byte_pointer)s,strlen(s));
解决了这一问题。
关于掩码运算
根据定义这里掩码是一个位模式,表示从一个字中选出的位的集合。根据计算x&OxFF
生成一个由x的最低有效字节组成的值,而其余的字节就被置为0。可是书上的例子X=Ox89ABCDEF和OxFF作&运算,为何结果Ox000000EF,后来知道在运算的时候须要将它换算成二进制数才能进行运算,十六进制没法直接进行运算。
关于有符号数和无符号数
建立按一个无符号常量,必须加上后缀字符“u”
或者“U”
。容许为无符号数和有符号数之间的转换,转换的原则是底层位保持不变。在转换时候能够采用隐式,这样就解决了书上p48的练习遇到的问题。
隐式相似于:
int x,y; unsigned ux, uy; x=ux; y=uy; 由于在代码段中省略了`x=(int)ux ; `因此在编写代码的时候容易出错,必定要区分清楚哪一个是符号数哪一个是无符号数。
书p28页关于强制转换
关于强制类型转换,最开始在编译代码的时候遇到了问题。
加上一个主函数mian()
,就能够解决。
可是要注意,定义输入数字的时候须要定义成float格式,float能够强制转换成lnt格式,可是若是定义成int格式,若是定义成int格式再强制转换成float格式会发生错误。
书p44页关于有符号和无符号数之间相互转换
C语言容许在各类不一样的数字数据类型之间作强制类型转换。
起初对于代码段
short int v = -12345 unsigned short uv = (unsigned short) v; printf(“v = %d ,uv = %u\n”,v,uv);
理解起来存在一些问题,后来套用到一个主函数中,gcc编译gdb设断点理解就会容易许多。
书p47页有符号数和无符号数和p49页扩展一个数字的位表示
C语言支持全部整型数据类型的有符号和无符号的运算。
将一个无符号数转换为一个更大的数据类型,在表示的开头添加0,称为零扩展。
将一个补码数字转换为一个更大的数据类型能够执行符号扩展。
将代码段套在一个main主函数中,编译运行一下就会容易理解许多。
代码传到开源中国代码托管:https://git.oschina.net/20145335/Linux-besti-is-20145335.git
已经学了三周的《深刻理解计算机系统》,这周学到的知识,补码,反码等,包括溢出等知识点虽然之前在计算机导论和c语言基础的课程上都有所了解,可是将这些知识点放在一个全新的Linux系统下理解就有不少的不同了,不论在理解方面仍是运用的方面都是新的知识。须要多加练习多多巩固,虽然这周的知识都偏向于基本知识,可是编程的须要也是必不可少的,对于一些代码段的理解仍是须要本身动手去实践编译和运行才能感悟更深。
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 180/200 | 2/2 | 18/20 | |
第二周 | 460/500 | 2/4 | 18/38 | |
第三周 | 650/1000 | 3/7 | 54/60 | 熟练使用gcc与gdb |