《深入理解计算机系统》笔记一:信息的表示与处理(1)——基本数据类型与字节序

来源:互联网 发布:手办淘宝店推荐贴吧 编辑:程序博客网 时间:2024/04/23 16:06

        基本数据类型与字节序

        第一章是绪论,总体讨论了计算机系统的实现方式,所以将两章合并到一起写


        题外话,《深入理解计算机系统》是卡内基.梅隆大学计算机本科的教材。不知道卡内基梅隆的可以Google下,计算机专业应该在全美能排上前三了,在这里感谢一下卡内基和梅隆这两位商业巨富,有了你们的无私奉献精神,才有了今天美国的富强。这本书很有名气,也买了很久了,期间粗略的翻阅过其中一些章节,一直没有系统的钻研过。借着考SA的机会,彻底通读一遍此书。软考中的知识点有组成原理,在选书的过程中,总觉得现在一些将组成原理的书写的太过枯燥了,也许是本人偏向软件(或者说对硬件一窍不通)的缘故。《深入理解计算机系统》不但详细讲解了计算机系统的组成,CPU的原理(这个有点偏向于体系结构),更为难能可贵的是,本书对硬件与软件的结合非常好,第二章《程序的机器级表示》,就是在讲解汇编语言的同时,把相应的汇编代码对应的C程序有机的结合起来,读起来兴趣盎然。如果有和我一样偏软件的却想重温组成原理和体系结构同学,强烈推荐你们看一下。


        本章主要是介绍计算机中数据是怎样存储的。先介绍几个基本的单位:

1. 位bit(b):       表示一个二进制数,最小的可寻址单位

2. 字节byte(B):计算机中处理数据的基本单位,由8个二进制位组成

3. 字:                总线传送的字节块

4. 字长:           CPU一次处理数据的位数。 字中的字节数/整数或指针的标准值,决定了虚拟存储空间的大小

5. 总线:            被设计成传送定长的字节块


编译器把文本文件编译成可执行文件的过程:

.c文件->cpp预处理器(.i文件)->ccl编译器(.s文件)->as汇编器(.o文件,可重定位)->ld链接器(可执行文件a.out)

其中,可重定位的文件,在后续的《Linkers and Loaders》笔记中详细描述,敬请关注。


控制器:在设备本身上或主板的芯片组

适配器:插在主板上插槽上的卡


内存:DRAM

高速缓存:SRAM


存储器层次结构:

寄存器->一级缓存->二级缓存->内存->硬盘->网络服务器


        上一个层次,作为下一个层次的高速缓存。这个思想尤为重要,大家都知道,我们在编写代码时,为了减少对磁盘的访问,增加速度,往往会把常常需要的数据存放在内存中,这就是缓存的思想。同理,CPU在访问内存时,为了提高效率,往往会预先把数据存放到高速缓存中(Cache),而现代的CPU,对cache的命中率,已经达到了90%甚至更高。而大家看在线的视频时,如果网速够快,播放器会先将视频下载到硬盘中,这时硬盘就作为网络服务器的高速缓存。


        编译器维护各种数据类型的信息,但实际生成的可执行程序却没有类型信息。也就是说CPU只是处理二进制,具体如何处理,要看根据实际代码生成的汇编文件来决定。故而编译器对类型的判断与转换至关重要,编程时切记要关注编译器关于类型转换的告警,否则类型错误的问题很不好查。


C语言中对类型范围的定义:

C语言对不同数据类型设置了下界,却没有设置上界

 

保证的

典型32位机

 

最小值

最大值

字节数

最小值

最大值

字节数

Char

-127

127

1

-128

127

1

Unsigned char

0

255

1

0

255

1

Short

-32767

32767

2

-32768

32767

2

Unsigned short

0

65535

2

0

65535

2

Int

-32767

32767

2

-2147483648

2147483647

4

Unsigned int

0

65535

2

0

4294967295

4

Long

-2147483647

2147483647

4

-2147483648

2147483647

4

Unsigned long

0

4294967295

4

0

4294967295

4

<limits.h>限定了机器的类型取值范围,可以通过INT_MAX,INT_MIN,UINT_MAX,UINT_MIN…这些宏,来获取当前环境(CPU,编译器)的C类型大小

下面是典型的32位机器和64位机器不同类型的具体大小。这里说“典型”,指的是并非所有32位和64位机器都是如此定义,编译器不同,具体的大小也不同。本人就在TC的环境下发现,int居然是2个字节的,不知道为何如此设计。

C类型

典型32位机

典型64位机

Char

1

1

Short

2

2

Int

4

4

Long

4

8

Pointer

4

8

Float

4

4

double

8

8


字节顺序和大小端(big/little endian):

        big/little endian这个计算机术语,出自《格利弗游记Gulliver's Travels》,就好比我国的《镜花缘》。书中描述了两个国家,这两个国家为了吃鸡蛋时先敲碎鸡蛋的大端还是小端争论不休,从而演变为连年的战争,其实是讽刺当年英法之间的百年战争。在学习技术的过程中穿插一些典故轶事,也颇为有趣

        大小端实际上是指CPU的制造厂商对于存放数据的一种不同形式。这两种形式在效率上没有差别,由于没有标准规定,所以造成了当今两种不同的实现。

        按照从最低有效字节到最高有效字节的顺序存储对象,叫做小端;按照从最高有效字节到最低有效字节的顺序存储对象,叫做大端

        假设int i = 0x01234567,i的高位字节为0x01,低位字节为0x67;i 占用四个字节,地址为0x100-0x103,如果按照大端存放,则高位字节0x01,放入最小的地址0x100,而低位字节0x67,放入最大的地址0x103中。如下图:

大端:

        低位字节                     高位字节

地址

0x100

0x101

0x102

0x103

01

23

45

67

也就是说,数据的高位,保存在低地址;数据的低位,保存在高地址。C语言的取址符&,都是从最低的地址开始取的,所以如果打印出来,会觉得跟我们正常顺序一样,但对计算机来说,恰好是反的。

小端:

         低位字节                  高位字节

地址

0x100

0x101

0x102

0x103

67

45

23

01

小端如果打印出来,会觉得跟我们正常顺序相反,但对计算机来说,是顺序的。


常用字符的ascii值:

0-9:0x30-0x39    48-57

A-Z:0x41-0x5a    65-90

a-z:0x61-0x7a    97-122


C语言的逻辑运算:

0:False  ~0:True

与AND:&&

或OR:||

非NOT:!

逻辑运算是从左至右结合的

如果前面的运算能得出结果了,那么后面的运算不会继续

a && 5/a:   不会除0

p&& *p++: 不会操作空指针


C语言的位运算:

与AND:&

或OR:|

非NOT:~

异或EXCLUSIVE-OR:^ 不同为真,相同为假

位运算是从左至右结合的


左移:向左移动k位,右端补k个0

右移:无符号数,逻辑右移;有符号数,可以算术右移,可以逻辑右移

1)     算术右移(绝大部分机器)

左边补最高有效位

00110011>>2 = 00 001100

11001100>>2 = 11 110011

2)     逻辑右移

左边补0

11001100>>2= 00 110011


先写到这里,接下来讨论有/无符号整数和浮点数的表示

原创粉丝点击