深入理解计算机系统2

摘要:
数字的有限字长限制了可能值的范围,结果运算可能溢出。我们已经看到,C语言中的一些规定可能会产生意想不到的结果,这可能是难以检测或理解的缺陷的来源。我们特别看到了无符号数据类型。虽然它在概念上非常简单,但即使对于高级程序员来说,它也可能导致意外的行为。我们还看到,这种数据类型会以意想不到的方式出现,例如在编写整数常量和调用库函数时。

第二章 信息的表示和处理

2.1 信息存储

  大多数计算机使用8位的块,或者字节(byte),作为最小的可寻址的内存单位,而不是访问内存中单独的位.机器级程序将内存视为一个非常大的字节数组,称为虚拟内存(virtual memory).内存的每个字节都由一个唯一的数字来标识,称为它的地址(ad-adress),所有可能地址的集合就成为虚拟地址空间(virtual address space).顾名思义,这个虚拟地址空间只是一个展现给机器级程序的概念性映像

2.1.1 十六进制表示法

深入理解计算机系统2第1张

2.1.2 字数据大小

深入理解计算机系统2第2张

2.1.3 寻址和字节顺序

深入理解计算机系统2第3张

2.1.4 布尔代数

深入理解计算机系统2第4张

2.1.5 位运算

这里进行一个知识补充:
对一个w位的数移动K位 下面的demo 假设 w = 32

int 1val = OxFEDCBA98<<32; 
int aval = OxFEDCBA98>>36; 
unsigned uval = OxFEDCBA98>>40;

// 实际上计算机执行的是
int 1val = OxFEDCBA98<<0; 
int aval = OxFEDCBA98>>4; 
unsigned uval = OxFEDCBA98>>8;

// 这是因为移位实际上是 num <> (k mod w)
// 做了取模运算

2.2 整数表示

  我们描述用位来编码整数的两种不同的方式:一种是只能表示非负数,而另一种能够表示负数、零和正数。

2.2.1 整型数据类型

32位程序上C语言整型数据类型的典型取值范围
深入理解计算机系统2第5张

64位程序上C语言整型数据类型的典型取值范围
深入理解计算机系统2第6张

C语言标准要求数据类型的取值范围
深入理解计算机系统2第7张

2.2.2 无符号数的编码

深入理解计算机系统2第8张

2.2.3 补码编码

深入理解计算机系统2第9张

2.2.4 有符号数和无符号数之间的转换

  C语言允许在各种不同的数字数据类型之间做强制类型转换.
  对于32位字长来说,无符号形式的4294967295(UMax32)和补码形式的-1的位模式是完全一样的.将 unsigned强制类型转换成 int, 底层的位表示保持不变.
  对于大多数C语言的实现,处理同样字长的有符号数和无符号数之间相互转换的一般规则是:`数值可能会改变,但是位模式不变`

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

  C语言支持所有整型数据类型的有符号和无符号运算.尽管C语言标准没有指定有符号数要采用某种表示,但是几乎所有的机器都使用补码
  C语言允许无符号数和有符号数之间的转换.虽然C标准没有精确规定应如何进行这种转换,但大所述系统遵循的原则是底层的位表示保持不变.

2.3 整数运算

2.3.1 无符号加法

深入理解计算机系统2第10张
深入理解计算机系统2第11张

深入理解计算机系统2第12张

深入理解计算机系统2第13张

2.3.2 补码加法

深入理解计算机系统2第14张
深入理解计算机系统2第15张

2.3.3 补码的非

深入理解计算机系统2第16张

2.3.4 无符号乘法

深入理解计算机系统2第17张

2.3.5 补码乘法

深入理解计算机系统2第18张

2.3.6 乘以常数

  在大多数机器上,整数乘法指令相当慢,需要10个或者更多的时钟周期,然而其他整数运算(例如加法、减法、位级运算和移位)只需要1个时钟周期.因此,编译器使用了一项重要的优化,试着用移位和加法运算的组合来替代乘以常数因子的乘法.

深入理解计算机系统2第19张
深入理解计算机系统2第20张

2.3.7 除以2的幂

  在大多数机器上,整数除法要比整数乘法更慢 —— 需要30个或者更多的时钟周期
  除以2的幂也可以用移位运算来实现,只不过我们用的是右移,而不是左移.无符号和补码数分别使用逻辑移位和算数移位来达到目的

深入理解计算机系统2第21张
深入理解计算机系统2第22张
深入理解计算机系统2第23张

2.3.8 关于整数运算的最后思考

  正如我们看到的,计算机执行的“整数”运算实际上是一种模运算形式。表示数字的有限字长限制了可能的值的取值范围,结果运算可能溢出。我们还看到,补码表示提供了一种既能表示负数也能表示正数的灵活方法,同时使用了与执行无符号算术相同的位级实现,这些运算包括像加法、减法、乘法,甚至除法,无论运算数是以无符号形式还是以补码形式表示的,都有完全一样或者非常类似的位级行为。
  我们看到了C语言中的某些规定可能会产生令人意想不到的结果,而这些结果可能是难以察觉或理解的缺陷的源头。我们特别看到了unsigned数据类型,虽然它概念上很简单,但可能导致即使是资深程序员都意想不到的行为。我们还看到这种数据类型会以出乎意料的方式出现,比如,当书写整数常数和当调用库函数时。

2.4 浮点数

深入理解计算机系统2第24张

2.4.1 二进制小数

深入理解计算机系统2第25张
深入理解计算机系统2第26张

2.4.2 IEEE浮点表示

深入理解计算机系统2第27张
深入理解计算机系统2第28张

2.4.3 舍入

因为表示方法限制了浮点数的范围和精度,所以浮点运算只能近似地表示实数运算.因此,对于值X,我们一般想用一种系统的方法,能够找到"最接近的"匹配值x1,它可以用期望的浮点形式表示出来.这就是舍入(rounding)运算的任务
深入理解计算机系统2第29张

2.4.5 C语言中的浮点数转换

  当在 int、float、double格式之间进行强制类型转换时,程序改变数值和位模式的原则如下(假设int是32位的)

深入理解计算机系统2第30张

2.5 小结

深入理解计算机系统2第31张
深入理解计算机系统2第32张

免责声明:文章转载自《深入理解计算机系统2》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇二、Web Service开发(.net)iOS开发UI篇—iPad和iPhone开发的比较下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C语言探索之旅 | 第一部分第三课:你的第一个程序

作者 谢恩铭,公众号「程序员联盟」。 转载请注明出处。 原文:https://www.jianshu.com/p/c73fecacd006 《C语言探索之旅》全系列 内容简介 前言 控制台程序还是窗口程序 最基础的代码 特殊字符 注释,很有用 总结 第一部分第四课预告 1. 前言 在上一课 C语言探索之旅 | 第一部分第二课:工欲善其事,必先利其...

C语言LIBCURL库使用注意事项

这里一个java程序员进行C++开发使用libcurl踩过的坑: 1.  发送指定请求类型body,比较通用方法如下,可以直接填写数据并手动指定content type,如果是form表单等形式,则需要参考curl_formadd方法 struct curl_slist *list = NULL; list = curl_slist_app...

C语言预处理理论-宏定义2

宏定义21、带参宏和带参函数的区别(1)宏定义是在预处理期间处理的,而函数是在编译期间处理的。这个区别带来的实质差异是:宏定义最终是在调用宏的地方把宏体原地展开,而函数是在调用函数处跳转到函数中去执行,执行完后再跳转回来。注:宏定义和函数最大差别就是:宏定义是原地展开,因此没有调用开销;而函数是跳转执行再返回,因此函数有比较大的调用开销。所以宏定义和函数相...

C语言Windows程序开发—CreateWindow函数介绍【第03天】

(一)CreateWindow函数的参数介绍: 1 HWND CreateWindow( 2 LPCTSTR lpClassName, //Windows窗口中预定义的控件结构体,包括:BUTTON(按钮),EDIT(文本框),LISTBOX(列表),MDICLIENT(子窗口),SCROLLBAR(滚动条),RICHEDIT(富文...

C语言中的正负数及其输出

在数学中,数字有正负之分。在C语言中也是一样,short、int、long 都可以带上正负号,例如: //负数 short a1 = -10; short a2 = -0x2dc9; //十六进制 //正数 int b1 = +10; int b2 = +0174; //八进制 int b3 = 22910; //负数和正数相加 lon...

c语言-格式控制字符 %XXd 用法

d格式字符 用来输出十进制整数,有以下几种用法: 1. %d, 按整型数据的实际长度输出。 2. %md,m为指定输出的整型位数的宽度,如果整型数据的实际位数小于m,则左端补以空格,如果大于m,则按实际位数输出。 3. %0md,同上,当整型数据实际位数小于m时,左端补以数字0,而不是空格。 4. %.md, 同%0md。 5. %ld, 按长整型数据输出...