第二章 信息的表示和处理

1.信息存储

大多数计算机使用8位的块,或者字节(byte),作为最小的可寻址的内存单位,而不是访问内存中单独的位。机器程序将内存视为一个非常大的数组,称为虚拟内存。内存的每个字节都由一个唯一的数字来标识,称为他的地址,所有可能地址的集合就称为虚拟地址空间。

1.1十六进制标识法

一个字节由8 位组成。

在C 语言中,以 0x 或0X 开头的数字常量被认为是十六进制的值。

1.2字数据大小

每台计算机都有一个字长,指明指针数据的标称大小。

有符号

无符号

32位

64位

[signed] char

unsigned char

1

1

short

unsigned short

2

2

int

unsigned

4

4

long

unsigned long

4

8

int32_t

uint32_t

4

4

int64_t

uint64_t

8

8

char*

4

4

float

4

4

double

8

8

为了比main由于依赖“典型”大小和不同编译器设置带来的奇怪行为,ISO C99 引入了一类数据类型,其数据大小是固定的,不随编译器和机器设置而变化:int32_t 和int64_t。

1.3寻址和字节顺序

对于跨越多字节的程序对象,我们必须建立两个规则:这个对象的地址是什么,以及在内存中如何排列这些字节。

排列标识一个对象的字节有两个通用的规则。

  • 最低有效字节在最前面的方式,称为小端法
  • 最高有效字节在最前面的方式,称为大端法

大多数intel 机器都只用小端模式

1.4表示字符串

C 语言中字符串被编码为一个以null 字符为结尾的字符数组。

1.5表示代码

计算机系统的一个基本概念就是,从机器的角度来看,程序仅仅只是字节序列。

1.6布尔代数简介

二进制是计算机编码、存储和操作信息的核心,所以围绕数值0和1的研究已经演化出了丰富的数学知识体系。

1.7C语言中的位级运算

C语言的一个很有用的特性就是它支持按位布尔运算。

1.8C语言中的逻辑运算

C语言还提供了一组逻辑运算符 || 、&& 和!。

1.9C语言中的移位运算

C语言还提供了一组移位运算,向左或向右移动位模式。

2.整数表示

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

2.1整型数据类型

C语言支持多种整型数据类型—表示有限范围的整数。

32位

C数据类型

最小值

最大值

[signed] char

-128

127

unsigned char

0

255

short

-32768

32767

unsigned short

0

65536

int

-2147483648

2147483647

unsigned

0

4294967295

long

-2147483648

2147483647

unsigned long

0

4294967295

int32_t

-2147483648

2147483647

uint32_t

0

4294967295

int64_t

-9223372036854775808

9223372036854775807

uint_64_t

0

18446744073709551615

64位

C数据类型

最小值

最大值

[signed] char

-128

127

unsigned char

0

255

short

-32768

32767

unsigned short

0

65536

int

-2147483648

2147483647

unsigned

0

4294967295

long

-29223372036854775808

9223372036854775807

unsigned long

0

18446744073709551615

int32_t

-2147483648

2147483647

uint32_t

0

4294967295

int64_t

-9223372036854775808

9223372036854775807

uint_64_t

0

18446744073709551615

2.2无符号数的编码

无符号数编码具有唯一性

2.3补码编码

补码编码具有唯一性

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

C语言允许在各种不同的数字数据类型之间做强制类型转换。

2.5C语言中的有符号数与无符号数

C语言支持所有整型数据类型的有符号和无符号运算。

C语言允许无符号和有符号之间的转换。

2.6扩展一个数字的位表示

一个常见的运算是在不同字长的整数之间转换,同时又保持数值不变。

要将一个无符号转换为一个更大的数据类型,我们只要简单地在表示的开头添加0。

2.7截断数字

当把一个长位类型转换位短位类型是,将长位类型截断位短位类型。

3.整数运算

表达式 x<y和表达式 x-y<0会产生不同的结果。这些属性是由于计算机预算的有限性造成的。理解计算机运算的细微之处能够帮助程序员编写更可靠的代码。

3.1无符号加法

两个非负整数相加,和的范围可能会超出数据类型长度,叫做“字长膨胀”。

3.2补码编加法

对于补码加法,和的范围可能正溢出,也可能负溢出。

3.3补码的非

对w 位的补码加法来说,TMin是自己的加法的逆。

3.4无符号乘法

无符号数相乘后截断为w位的模。

3.5补码乘法

通过将2w位的乘积截断为w位来实现的。

3.6乘以常数

整数乘法指令相当慢,编译器使用一项重要的优化,试着用移位和加法运算的组合来代替乘以常数因子的乘法。

无论是无符号运算还是补码运算,乘以2的幂都可能会导致溢出。

3.7除以2的幂

在大多数机器上,整数除法要比整数乘法更慢。除以2的幂也可以用移位运算实现,只不过我们用的是右移,而不是左移。

4.浮点数

浮点表示对形如V=v*2^y 的有理数进行编码。

4.1二进制小数

理解浮点数的第一步是考虑含有小数值的二进制数字。

4.2IEEE浮点表示

IEEE 浮点标准用 V=(-1)^sM2^E的形式来表示一个数

  • 符号s决定这个数是负数(s=1)还是正数(s=0),而对于数值0的符号位解释作为特殊情况处理。
  • 尾数M是一二进制小数,它的范围是1~2-e,或这是0~1-e。
  • 阶码E的作用是对浮点数加权,这个权重是2的E次幂(可能是负数)。
  • 一个单独的符号位s直接编码符号s。
  • k位的阶码字段 exp=e(k-1)...e(1)e(0)编码阶码E。
  • n 位小数字段 frac=f(n-1)...f(1)f(0)编码尾数M,但是编码出来的值也依赖于阶码字段的值是否等于0。

4.3数字示例

4.4舍入

因为表示方法限制了浮点数的范围和精度,所以浮点运算只能近似地表示实数运算。IEEE浮点格式定义了四种不同的舍入方式。默认的方法是找到最接近的匹配,而其他三种可用于计算上界和下界。

4.5浮点运算

IEEE标准指定了一个简单的规则,来确定注入加法和乘法这样的算术运算的结果。

IEEE标准中指定了浮点运算行为方法的一个优势在于,他可以独立于任何具体的硬件或者软件实现。

前面我们看到了整数加法形成了阿贝尔群。实数上的加法也形成了阿贝尔群,但是我们必须考虑舍入对这些属性的影响。

浮点加法不具有结合性,这是缺少的最重要的群属性。

对于科学计算程序员和编译器编写者来说,缺乏结核性和分配性是很严重的问题。

4.6C语言中的浮点数

所有的C语言版本提供了两种不同的浮点数据类型:float和double。

5.小结

计算机将信息编码为位(比特),通常组织成字节序列。

C语言的设计可以包容多种不同字长和数字编码的实现。

大多数机器对整数使用补码编码,而对浮点数使用IEEE标准754编码。

在相同长度的无符号和有符号整数之间进行强制类型转换时,大多数C语言实现遵循的原则是底层的位模式不变。

由于编码的长度有限,与传统整数和实数运算相比,计算机运算具有非常不同的属性。

和大多数其他程序语言一样,C语言实现的有限整数运算的真实的运算相比,有一些特殊的属性。

浮点表示通过数字编码位x*2^y的形式近似地表示实数。

必须非常小心地使用浮点运算,因为浮点运算只有有限的范围和精度,而且并不遵守普通的算术属性,比如结合性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值