购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 进制换算

进制换算就是数值在不同的计数制之间进行的等值或等价换算,数值在换算前后保持不变,只是表达方式不同而已。计数制是为不同的计数单位制定的标准。

2.2.1 进位计数制概述

通常,在我们日常生活中最习惯应用的是十进制,但实际应用中也会使用其他计数制,例如,十二进制(一打鸡蛋为十二个),六十进制(60 秒为一分钟,60 分钟为一小时)等,这种逢几进一的机制称为进位计数制。与C语言关系最密切的几种计数制是二进制、八进制、十进制和十六进制。

二进制是只使用 0 和 1 的计数制,采用逢二进一的进位方式。由于可以使用 0 和 1 分别代表电路中的高电平和低电平,因此现代电子计算机数据存储机制大都采用二进制。由于二进制不易读写和计算,因此产生了八进制和十六进制计数制。八进制共有 0、1、2、3、4、5、6、7 八个数,采用逢八进一的进位方式。十六进制共有 0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F十六个数,采用逢十六进一的进位方式。十六进制中字母部分不区分大小写,从A到F分别代表十进制数 10、11、12、13、14、15。另外还有日常生活中最常用的十进制,共有 0、1、2、3、4、5、6、7、8、9 十个数,采用逢十进一的进位方式。如表 2-1 所示为几种进制的基本规则,其中基数、数码和位权的概念在下节讲解中做详细描述。

表 2-1 几种进制基本规则

2.2.2 二进制与其他进制转换

二进制数是由 0 和 1 组成的数字,下面介绍如何表示和计算二进制以及与其他进制的关系。

1. 二进制转换十进制

二进制转换为十进制分成两部分进行,一部分是整数部分,另一部分是小数部分,转换方法如范例 2.1 所示。

范例2.1 :将二进制数10010.11 (2) 转换为十进制数

解析:通常将二进制数做这样的换算

10010.11 (2) = 1x2 4 +0x2 3 +0x2 2 +1x2 1 +0x2 0 +1x2 -1 +1x2- 2 = 18.75 (10)

算式中下标(2)和(10)称做基数,同时也是计数单位;2 x 称做位权;0 和 1 称做数码。计算时幂指数可由右向左按数码位置从 0 算起,如右边最低位数码 1 对应的位权幂指数为 0,由此我们计算得二进制数 10010.11 (2) 相当于十进制数 18.75 (10)

2. 二进制转换八进制

二进制到八进制的转换采用三位一体的计算方法,同样分为整数和小数两部分考虑。如下示例:

100111.01101 (2) = 47.32 (8)

二进制到八进制的转换方法为将二进制数整数部分从右到左(小数部分从左到右),按每三位划分为一组,最左边(右边)不够三位的补 0。如上述算式中 100111.01101—〉100/111/011/010,将每组对应的八进制数代替二进制数,得到 4/7/3/2,去掉分隔符,得到八进制数 47.32。二进制与八进制的对应关系请查阅表 2-2 所示,二进制栏粗体部分表示对应八进制时的数组合。

范例2.2 :将二进制数1110100.101101 (2) 转换为八进制数

解析:按照三位一体的方法,将二进制数从右到左每三位划分为一组。查表 2-2 所示,将各组改为对应的八进制数,得到八进制数的结果。

计算流程如下:

1110100.101101 (2) → 001/110/100/101/101 (2) → 1/6/4/5/5 (8) =164.55 (8)

3. 二进制转换十六进制

二进制到十六进制的转换采用四位一体的计算方法,计算时同样整数部分与小数部分分开,如下示例:

100111.01101 (2) = 27.68 (16)

和二进制到八进制的转换方法类似,二进制到十六进制的转换方法为将二进制数整数部分从右到左(小数部分从左到右)按每四位划分为一组,最左(右)边不够四位的补 0。如上述算式中 100111.01101—〉0010/0111/0110/1000,将每组对应的十六进制数代替二进制数,得到 2/7/6/8,去掉分隔符,得到十六进制数 27.68。二进制与十六进制的对应关系请查阅表2-2 所示。

范例2.3 :将二进制数1110100.101101 (2) 转换为十六进制数

解析:按照四位一体的方法,将二进制数从右到左每四位划分为一组。查表 2-2 所示,将各组改为对应的十六进制数,得到十六进制数的结果。

计算流程如下:

1110100.101101 (2) → 0111/0100/1011/0100 (2) →7/4/B/4 (16) =74.B4 (16)

表 2-2 进制转换表

2.2.3 八进制与其他进制转换

八进制数由 0、1、2、3、4、5、6、7 这八个数组成,与二进制到其他进制的转换类似,八进制向其他进制的转换也有一定的规则,本书只讨论整数形式的八进制向其他进制的转换。

1. 八进制转换为十进制

八进制向十进制的转换也要按照位权和数码相乘再依次相加的方法。例如,下面的数制转换等式:

1270 (8) = 696 (10)

与二进制到十进制的转换类似,上式中八进制数 1270 到十进制的转换计算公式为:

1270 (8) = 1x8 3 +2x8 2 +7x8 1 +0x8 0 =696 (10)

算式中下标(8)和(10)称做基数,同时也是计数单位;8 x 称做位权;0、1、2 和 7 称做数码。计算时幂指数可自右向左按数码位置从 0 算起。如右边最低位数码 7 对应的位权幂指数为 0。由此我们计算得八进制数 1270 相当于十进制数 696。

2. 八进制转换为二进制

八进制数向二进制数的转换可以看做是二进制到八进制的逆运算。八进制到二进制的转换方法为将八进制数从右到左每位数字转换为 3 位二进制数,转换方法请参看表 2-2 所示,并去掉最左边的 0 位。

范例2.4 :将八进制数5361 (8) 转换为二进制数

解析:将八进指数从右到左依次转换为二进制数,计算方法为

5361 (8) →101/011/110/001 (2) →101011110001 (2)

注意:转换时每位八进制数字一定写满 3 位数的二进制,如 1→001,而不能写成 1→01或者 1→1。

3. 八进制转换为十六进制

八进制到十六进制的转换通常以二进制为中介,即先将八进制转换为二进制,然后再由二进制转换为十六进制。

范例2.5 :将八进制754231 (8) 转换为十六进制

解析:先将八进制数 754231 (8) 转换为二进制

754231 (8) →111/101/100/010/011/001 (2) →111101100010011001 (2)

再将二进制转换为十六进制

111101100010011001 (2) →0011/1101/1000/1001/1001 (2) →3/D/8/9/9 (16) →3D899 (16)

2.2.4 十六进制与其他进制转换

十六进制数是C语言中主要的赋值方式之一,同时也是二进制在C语言中的主要表现方式,在后续章节的C语言内存讲解及程序调试过程中,它将会得到广泛地使用。

1. 十六进制转换为十进制

十六进制向十进制的转换同样按照位权和数码相乘再依次相加的方法。例如,下面的数制转换等式:

13FB (16) = 5115 (10)

与二进制、八进制到十进制的转换类似,十六进制数 13FB (16) 到十进制的转换计算公式为:

13FB (16) = 1x16 3 +3x16 2 +Fx16 1 +Bx16 0 =1x16 3 +3x16 2 +15x16 1 +11x16 0 =5115 (10)

算式中下标(16)和(10)称做基数;16 x 称做位权;1、3、F和B称做数码。计算时幂指数可自右向左按数码位置从 0 算起,计算得十六进制数 13FB相当于十进制数 5115。

2. 十六进制转换为二进制

十六进制数向二进制数的转换可以看做是二进制到十六进制的逆运算,转换方法为将十六进制数从右到左每位数字转换为 4 位二进制数,转换方法请参看表 2-2 所示,并去掉最左边的 0 位。

范例2.6 :将十六进制数FB1A4 (16) 转换为二进制

解析:将十六进制数从右到左每位转换为 4 位二进制数

FB1A4 (16) →1111/1011/0001/1010/0100 (2) →11111011000110100100 (2)

3. 十六进制转换为八进制

十六进制转换为八进制同样需要二进制做中介。

范例2.7 :将十六进制数3C6D (16) 转换为八进制数

解析:先将十六进制数 3C6D (16) 转换为二进制

3C6D (16) →0011/1100/0110/1101 (2) →11110001101101 (2)

再将其转换为八进制

11110001101101 (2) →11/110/001/101/101 (2) →3/6/1/5/5 (8) →36155 (8)

2.2.5 十进制与二进制的转换

十进制到二进制的转换分成两部分,一部分是整数部分的转换,另一部分是小数部分的转换。

1. 整数部分转换

整数十进制到二进制的转换采用除二取余再反向的方法,即将整数做除二取余运算,直到被除数为零,然后将余数反向顺序写出,就是整数部分的二进制表达。

范例2.8 :将十进制数158转换为二进制数

解析:首先对 158 进行除二取余运算

158/2=79......0

79/2=39 ......1

39/2=19 ......1

19/2=9 ......1

9/2=4 ......1

4/2=2 ......0

2/2=1 ......0

1/2=0 ......1

等号右边是每次运算所得的商,省略号后面是本次运算的余数,将所得余数自下而上按顺序从左到右写出 10011110,这就是十进制数 158 的二进制表示。

2. 小数部分转换

小数部分十进制到二进制的转换采用乘二取整再顺序写出的方法,即将小数部分与 2 相乘,记录乘积的整数部分,将小数部分再与 2 相乘,记录乘积的整数部分,这样执行下去直到小数部分为 0 或满足要求精度。将所记录的整数部分按前后顺序从左往右写出,即得二进制形式。

范例2.9 :将十进制数0.375转换为二进制数,要求精确到小数点后6位

解析:对二进制数 0.375 做乘 2 取整运算

0.375*2=0.700 ......0

0.700*2=1.400 ......1

0.400*2=0.800 ......0

0.800*2=1.600 ......1

0.600*2=1.200 ......1

0.200*2=0.400 ......0

将上述所记录整数部分顺序写出 0.010110,这就是小数 0.375 的近似二进制表达。

作者心得:

十进制小数到二进制的转换经常遇到无限循环的情况,这时需要指定转换的精度,例如需要精确到小数点后 8 位,计算到二进制小数点后 8 位即可停止运算。

2.2.6 机器数及其在内存中存储格式

在计算机中,数据是以二进制形式存储的,而在内存中二进制数以字节为单位进行存储。通常,C语言中会经常提到描述二进制数的两个概念bit和byte,前者是一个二进制位 0 或 1,后者是指一个字节,表示 8 个二进制位。在内存中以二进制存储的数据称为机器数,机器数的存储有几种不同的表示方式,分别叫做原码、反码和补码。

1. 机器数

机器数的表示形式为用“0”表示正数,“1”表示负数,其余位表示数值,通常把在计算机内存中正、负号数字化的数称为机器数。C语言中的基本整型数据在计算机中通常用 32位(即 4 个字节)来存储,后续章节中将会讲解有关 32 位机的概念。

2. 原码

原码是计算机中数据存储方式之一,其表示形式为数值用绝对值表示,在数值的最高位用“0”和“1”分别表示数值的正和负。

范例2.10 :写出+35和-35的原码表示形式(32位表示)

解析:首先确定数据的符号作为最高位,然后将数值转换为二进制数,以 32 位表示

[+35] 原码=00000000000000000000000000100011

[-35] 原码=10000000000000000000000000100011

注意:0 的原码有两种表示方式,即正 0 和负 0,分别为

[+0] 原码=00000000000000000000000000000000

[-0 ]原码=10000000000000000000000000000000

3. 反码

反码在计算机中的表示方式为正数的反码与原码相同,负数的反码是其原码数值部分按各位取反,符号位不变。

范例2.11 :写出+35和-35的反码表示形式(32位表示)

解析:首先分别写出两个数的原码,以 32 位表示

[+35]原码=00000000000000000000000000100011

[-35]原码=10000000000000000000000000100011

再将负数 35 的原码取反,得+35 和-35 的反码

[+35]反码=00000000000000000000000000100011

[-35]反码=11111111111111111111111111011100

4. 补码

计算机补码的表示形式为正数的补码与原码、反码相同,负数的补码是其反码加 1,符号位不变。

范例2.12 :写出+35和-35的补码表示形式(32位表示)

解析:首先分别写出两个数的原码,以 32 位表示

[+35]原码=00000000000000000000000000100011

[-35]原码=10000000000000000000000000100011

再将负数 35 的反码加 1,得+35 和-35 的补码

[+35]补码=00000000000000000000000000100011

[-35]补码=11111111111111111111111111011101

5. 0的反码和补码

在反码和补码表示中,0 是一个比较特殊的数字,由于 0 可表示为正 0 和负 0,因此 0的原码和反码分别有两种表示形式,如下表示

[+0]原码=00000000000000000000000000000000

[-0]原码=10000000000000000000000000000000

[+0]反码=00000000000000000000000000000000

[-0]反码=11111111111111111111111111111111

而对于+0 和-0 的补码,有

[+0]补码=00000000000000000000000000000000

[-0]补码=00000000000000000000000000000000

可见 0 的补码表示是唯一的。 sAMfpnI0zTZziniZkp1kOvuhA2S+OGOCb6JWkOu0I+UwLQvDmydSv2/pshucsXEt



2.3 常量

在程序执行过程中,其值不发生改变的量称为常量,常量与数据类型结合又可分为整型常量、浮点常量、字符常量和枚举常量。在程序中,常量可以不经说明直接引用。

例如,有如下语句:

该语句为赋值语句,表示将整型常量 10 赋给变量I,其中数字 10 即为整型常量,属于正确引用,但由于变量i未经定义就进行引用,程序编译将会出现错误。

2.3.1 整型常量

常用的整型常量有八进制、十进制和十六进制三种。

1. 八进制常量

八进制常量必须以数字 0 开头,数码取值为 0~7。八进制数通常是无符号数,以下均是合法的八进制数 022,0110,0177777 等。以下均是不合法的八进制数 123(无前缀 0),0492(含有非八进制数码),-0127(出现了负号)等,

2. 十六进制常量

十六进制常量必须以 0X或 0x开头,其数码取值为 0~9,A~F或a~f。以下均是合法的十六进制数 0XB5,0X10,0XFFFF等。以下均是不合法的十六进制数B6(无前缀 0X),0X3G(含有非十六进制数码)等。

3. 十进制常量

十进制常量没有前缀,其数码为 0~9。以下均是合法的十进制数 23,-70,65535,1024等。以下均是不合法的十进制数 023(不能有前缀 0),23D(含有非十进制数码)等。

不同进制的数可以以同一种格式输出,也可以以不同格式输出,范例 2.1 说明了不同进制常量的数值表示。

范例 2.13
OutputInteger.c

OutputInteger.c:整型常量中八进制、十进制和十六进制的输出格式分别为%o, %d和%x,使用不同的格式,输出结果就是对应的表示形式,输出整数 521, 0521 和 0x521 的几种表示方法。

(光盘\chat2\ OutputInteger.c)

上述代码第 4、第 5 和第 6 行分别按八进制、十进制和十六进制输出三个不同的整型常量 521,0521 和 0x521,输出结果为:

作者心得:

C语言中,整型常量可用后缀加字母“l”或“L”表示长整型,如 034L表示长整型八进制数 034。32 位机中,长整型和普通整型没有区别。

2.3.2 实型常量

实型也称为浮点型。C语言中,实型常量也称为实数或者浮点数,并且实型常量只采用十进制表示形式。实型常量的表达方式有两种小数形式与指数形式。

1. 小数形式

实数的小数形式由数字 0~9 以及小数点组成。其中,小数点前仅有零位时,数字 0 可省略,小数点后仅有 0 位时,数字 0 也可以省略。例如:0.391、 14.0、.556、-33.等均为合法的实数。

2. 指数形式

实数的指数形式由十进制数码、阶码标志e或E以及阶码组成,其中阶码包括阶符和阶数两部分,阶符可为+或-,其中+可省略,阶数只能是十进制正整数或零,阶码不能省略。指数形式的一般表达方式为a E n,其中,a为十进制数,n为阶码,如+5、-6 及+9 等均为阶码。

如实数 314159.26 可表示为 3.1415926E+5、3.1415926e5 或 314.15926E+3 等。其中,把3.1415926E+5 这种形式称为“规范化的指数形式”,即十进制数码绝对值为大于 1 小于 10的数。

实型常量可通过加后缀f或F表示,如 58f和 785F分别表示实型常量 58 和 785,其内存所占空间与整型常量 58 和 785 有所不同。

2.3.3 字符常量

字符常量是C语言程序中应用非常广泛的一类常量,通常它是用单引号引起来的一个字符,字符常量在内存中占一个字节的内存空间。

1. 普通字符

例如'm','n','@','+','?'都是合法字符常量。在C语言中,字符常量有以下特点。

(1) 字符常量只能用单引号引起来,不能用双引号或其他括号。

(2) 字符常量只能是单个字符,不能是字符串。

(3) 字符可以是字符集中任意字符,但数字被定义为字符型之后就不能以原数值参与数值运算。如'0'和 0 是不同的,'0'是字符常量,但它仍能参与运算,不同的是需要将其转化为对应的ASCII码值 48。

例如下面的代码:

程序输出:

说明以整型格式输出时字符'0'将以其ASCII码值 48 输出。

2. ASCII码

ASCII 码(American Standard Code for Information Interchange)美国国家信息交换标准码。ASCII码使用一个字节表示不同的字符,最多可以定义 256 个字符,目前已定义 128 个,其中包括字母、数字、标点符号、控制字符及其他特殊符号的数值。它是国际标准化组织ISO(International Organization for Standardization)批准的国际标准码。

ASCII 字符集共有 128 个字符,其中 96 个可打印字符,包括常用的字母、数字、标点符号等,其他 32 个为控制字符。ASCII 字符集及其编码见附表 1。

C语言中常用的ASCII码是字母和数字集合,如A的ASCII值为 65,a的ASCII值为 97。

3. 转义字符

转义字符是一种特殊的字符常量。转义字符以反斜杠“\”开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。例如,在hello程序中printf函数中用到的“\n”就是一个表示换行的转义字符。常用的转义字符及其含义参见表 2-3 所示。

表 2-3 转义字符表

转义字符中最常用的是换行符“\n”,在很多输出语句中将使用它进行打印换行。

2.3.4 字符串常量

C语言中,字符串常量是由一对双引号引起来的字符序列,每个字符串都以'\0'作为结束标志。字符串常量在内存中存储时,系统在字符串的末尾自动添加字符串结束符'\0'。因此,在C语言程序中,n个字符的字符串常量,在内存中占有n+1 个字节的存储空间。

例如,字符串“Hello”包含 5 个字符,而在内存中占 6 个字符,系统在字符串结尾会添加结束符“\0”。需要特别注意的是,对于单个字符和字符串的区别,范例 2.14 说明了这种区别。

范例 2.14
Charstringdifferent.c

Charstringdifferent.c这里通过sizeof运算符解释单个字符时字符常量和字符串常量在内存中所占字节数的差别。

(光盘\chat2\Charstringdifferent.c)

sizeof是C语言中用于获取对象内存字节数的特殊运算符,这里分别获取了字符“a”和字符串“a”在内存中所占字节数。程序第 4 行和第 5 行分别通过sizeof运算符获取字符“a”和字符串“a”的内存字节数,在获取字符所占内存空间时使用了强制类型转换,原因请查看疑难解决 2。程序运行输出结果:

字符'a'和字符串"a"在内存中的逻辑存储如图 2-2 所示。

图 2-2 字符'a'和字符串"a"

作者心得:

范例 2.14 代码中printf函数内的说明字符串"char 数据类型长度: "和"string 数据类型长度:"使用了中文作为说明字符串。在Visual C++6.0 编程环境中,避免使用中文字符串,应尽量使用英文和拼音来表达。本书为便于读者理解,均使用了中文,读者在实际编写程序时应尽量避免这类情况。 62K2tpsxL0qOsgEh5STp6dq5zfa//6J+jUZa3wp+Y4Iv7Elo/SVHErmawXqobi9r



2.4 变量

变量可分为整型变量、实型变量、字符型变量等,整型变量按照有无符号分为有符号整型(signed)和无符号整型(unsigned)两类,按照所表达的数值范围和占内存字节数可分为短整型(short int)、基本整型(int)和长整型(long),某些系统还支持长长整型(long long)。同时,各类型又分有符号和无符号两类。实型变量主要有两种形式单精度浮点型(float)和双精度浮点型(double)。

2.4.1 变量与内存结构

对于整型变量而言,通常的操作系统默认都是有符号类型,如果定义无符号类型,需在前面加unsigned。

1. 计算机操作系统位长

计算机的内存结果是按照字节为单位进行信息存储,每个字节都有一个唯一的数字标识,通常将这个标识称为地址或物理地址。地址有长有短,从 1 字节到 8 字节不等,计算机操作系统按照内存地址的长度可分为 8 位机、16 位机、32 位机以及 64 位机等。

8 位机指内存地址为 1 字节数,地址值通常使用十六进制数表示,如 0xFB,0x12 等。通常较简单的单片机采用 8 位地址方式,称为 8 位机。

目前最常用的是 32 位机,即地址长度为 32bit,共 4 字节,例如,0x0012ff65,0x001B56FF。32 位机最大取址范围为 0x00000000-0xFFFFFFFF,共 4 GB内存。通常C语言中会使用其中一部分,如无特别说明,本书程序全部基于 32 位机。

2. 32位机计算机操作系统

32 位机中,短整型(short)在内存中占 2 字节,基本整型(int)在内存中占 4 字节,长整型(long)在内存中占 4 字节等。64 位机中还有长长整型(long long),在内存中占 8 字节。单精度浮点型(float)在内存中占 8 字节,双精度浮点型(double)在内存中占 16 字节。字符型变量可分为有符号和无符号两种类型,有符号字符型(char)和无符号字符型(unsigned char),两者在内存均占 1 字节。如表 2-4 所示为不同类型变量在内存中所占字节数。

表 2-4 数据类型内存结构表

C语言中可通过运算符sizeof获取数据类型内存字节数。

范例 2.15
MemoryTypeByte.c

MemoryTypeByte.c使用运算符sizeof获取不同数据类型在内存中所占的字节数,然后通过输出打印,由此可以直观地显示各种数据类型的内存字节数。

(光盘\chat2\MemoryTypeByte.c)

程序中第 4、5 和第 6 行分别使用了sizeof运算符,用于获取对象在内存中所占字节数,对象可以是变量、常量、指针、结构体等,后续章节将对该函数的应用做详细介绍。执行上述代码,输出结果为:

2.4.2 变量的定义

C语言规定,变量必须先定义后使用,未经定义的变量在使用时会提示错误而导致程序编译无法通过,合理定义变量和利用变量,将对程序的执行效率产生重要影响。

1. 怎样定义变量

变量在使用前需要先定义,其定义的一般形式有两种:

类型说明符是指要定义的变量类型,如整型变量的类型说明符为int、short或long等。如定义整型变量i,j,k,可以这样定义:

C语言中,这种表达叫做语句,分别表示定义 3 个int型的变量I,j,k。语句是C语言中的基本程序结构,并且必须以“;”作为语句的结束符,分号不可省略。

也可以将定义放在同一个语句中:

变量名也称为用户标识符,变量名的定义应遵循一定的规则。

(1) 由字母、数字和下划线组成。

(2) 变量名不能和关键字相同。

(3) 第一个字符必须是字母或下画线。

关键字是由C语言规定的具有特定意义的字符串,通常也称为保留字。用户定义的变量等标识符不应与关键字相同。C语言的关键字主要分为类型说明关键字和流程控制关键字两类,如表 2-5 所示为关键字表。

对每个关键字的详细说明,请参看附表 2,本书将在后续章节中依次讲解每个关键字的作用和用法。同时,最新的C语言语法版本中,将bool也列为关键字之一。

用户定义的变量名(用户标识符)不得与关键字相同,同时必须满足上述另外两个条件,如下列变量名均是非法的变量名 3i,int,ysl@163.com,_myname!,bool等。

表 2-5 关键字表

2. 变量赋初值

在变量定义的同时,还可以进行赋值操作,称做变量赋初值,如下定义:

像这种在定义变量的同时并赋予其一定值的操作称为变量赋初值。等价于下面语句:

当在一条语句中定义多个变量时,可以使用逗号表达式作如下定义方法:

关于逗号表达式的概念将在第3章中予以介绍,需要注意的是,不能使用如下方法给不同变量赋相同的值:

但可以在定义之后进行赋值操作,如:

此外,对于单个变量的赋值,可以在定义时进行,也可以在定义之后进行。

2.4.3 整型变量

前面已经讲过,整型变量按照在内存中所占字节长度分为短整型(short)、基本整型(int)、长整型(long)等,其中short、int和long称为类型说明符。C语言系统通过这些关键字判断不同类型的变量,从而为其分配相应的内存空间。

范例 2.16
IntegerVariableDefine.c

IntegerVariableDefine.c 分别定义short、int和long型的整型变量,打印输出各个变量的值,并输出各种整型变量在内存中所占字节数。

(光盘\chat2\ IntegerVariableDefine.c)

程序第 4、第 5 和第 6 行分别定义 3 种类型的变量I、j和k并赋初值。程序第 7 行输出3 个参数的值,第 8 行分别输出 3 个参数的内存长度。程序运行输出结果为:

虽然变量i、j和k的值相同,但它们在内存中的存储结构却不尽相同,如图 2-3 所示为不同变量类型在内存中的结构示意图。

需要注意的是,在内存中数值以二进制形式存放,并以十六进制形式显示,所以对于十进制数 10,在内存中会以十六进制a显示。

变量在使用前应先定义,若未定义就使用某变量,程序编译时将出现错误,若去掉程序第 4 行,在编译时将出现如下错误:

错误原因是使用了未定义的标识符i。因此,在使用变量前一定记住先定义该变量,这对于程序初学者是经常犯的错误。

变量在使用前除了先定义,还要赋初值。赋值方式可以先定义后赋值,也可以在定义的同时赋初值。若使用了未经赋值的变量,则将出现不可预期的结果。

范例 2.17
InitialVariable.c

InitialVariable.c 定义整型变量i、j和k,未给变量i赋值便使用该变量,输出i、j和k的值,检查使用未赋值变量的输出结果。

(光盘\chat2\ InitialVariable.c)

程序第 7 行最后一个输出格式控制用于输出表达式i+j+k,用以验证未赋值参数参与运算后的输出结果。程序输出结果为:

程序输出了无法预料的结果-13108 和-13088,这是由于变量i未经赋值便进行了引用,通常称这种不确定值为垃圾值。为避免这类垃圾值影响程序正确结果,一般在变量定义时赋初值 0,如无特别说明,本书后续章节都将遵循这一约定。

2.4.4 实型变量

实型变量分为单精度型(float)和双精度型(double)两类。单精度型变量占 4 个字节,精确位数为 7 位有效数字;双精度型变量占 8 个字节,精确位数为 16 位有效数字。实型变量的定义和整型变量类似,如:

分别表示定义单精度型变量p1, p2, p3 和双精度型变量x1, x2, x3。

范例 2.18
RealTypeVariable.c

RealTypeVariable.c 分别定义float和double型的变量,为两变量赋相同的值,并打印输出,检查两者输出值的差别。

(光盘\chat2\ RealTypeVariable.c)

程序第 4 行和第 5 行分别定义了float型和double型变量i和j,程序第 6 行和第 7 行分别对这两个变量赋初值以验证不同类型的精度。程序运行输出:

程序第 8 行输出语句中%.10f格式为输出小数点后 10 位数字。导致出现不同结果原因是float型和double型的精确度不同。

实型变量在内存中的数据存储格式按照符号位、指数位和尾数 3 部分。符号位表示数字的正负,指数位表示数字的指数大小,尾数部分表示小数点后能够精确的位数。如图 2-4 所示为float型和double型变量在内存中的存储形式。

图 2-4 实型变量存储结构

图 2-4(a)所示表示float型变量在内存中的存储结构,最高位为符号位,前 23 位(第

0 到第 22 位)为尾数位,中间 8 位(第 22 到第 30 位)为指数位。图 2-4(b)所示表示double型变量在内存中的存储结构,最高位为符号位,前 52 位(第 0 到第 51 位)为尾数位,中间11 位(第 52 到第 62 位)为指数位。

需要说明的是,在计算机中数据以二进制存储,因此上述各位值同样以二进制形式存储在计算机中,并且以规范化的指数形式存放。float型中,23 位二进制可表示十进制小数部分7 位,double型中,52 位二进制小数可表示十进制小数部分 16 位。

因此,float型只能精确到小数点后 7 位,其中第 7 位采用四舍五入,而double型则能精确到小数点后 16 位,能够准确输出所表达数据。

2.4.5 字符变量

字符变量在内存中占 1 个字节,类型说明符为char。与整型变量和实型变量的定义类似,字符型变量的定义格式为:

表示定义了一个字符变量a,变量a可以被赋予任何字符常量和整型值。由于字符变量只占用 1 个字节,因此只能存放 1 个字符数据。在内存空间中,字符是以ASCII码值存放的,例如字符'a'在内存中存放的是其ASCII码值 97。正因为字符在内存中的这种存储模式,通常也把字符变量当做取值在 0~127 之间的整型量看待,并且字符变量也可以参与算数运算。

范例 2.19
CharacterVariableCalc.c

CharacterVariableCalc.c 分别定义整型和字符型变量,以整型和字符型打印输出,检查输出结果。

(光盘\chat2\ CharacterVariableCalc.c)

程序第 4 行和第 5 行分别定义了char型和int型变量c和i,程序第 6 行和第 7 行分别按不同的输出格式输出这两个变量,以验证两种数据类型的通用性。程序运行输出:

因为在ASCII码表中,大写字母A是 65,小写字母a是 97,两者相差 32,程序正是利用这一规律实现了使用算术运算进行大小写字母转换。这一方法在工程应用中被广泛采用。 62K2tpsxL0qOsgEh5STp6dq5zfa//6J+jUZa3wp+Y4Iv7Elo/SVHErmawXqobi9r

点击中间区域
呼出菜单
上一章
目录
下一章
×