1、第 1 章 C 语言概述C 语言是一门十分优秀的经典开 发语言。 1972 年,美国贝尔实验室的 Dennis M. Ritchie在 B 语 言的基础上设计发明了 C 语言,并首次用 C 语言改写了 Unix 操作系统。随后 C 语言被使用在多种计算机上,并广泛 应用在各个领域, 风靡全球。后来,美国国家标准学会(ANSI)为 C 语言制定了一个统一的标准,成 为现行的 C 语言标准。通过阅读本章,您可以: 了解 C 语言的优势。 掌握二进制数与十进制数的转换方法。 掌握二进制数与十六进制数的转换方法。 掌握二进制数与八进制数的转换方法。 掌握计算机中定点数与浮点数的表示方法。2跟我学 C
2、语言1.1 为什么要选择 C 语言目前世界上流行的计算机编程语言有许多种,如C、C+ 、Java 、C#、Pascal、Basic、Fortran。为什么要选择 C 语言呢?下面就来说明选择C 语言有哪些好处。1.1.1 选择 C 语言的好处C、C+、Java 、C#、Basic 是目前非常流行的编程语言,每个程序员不一定都精通,但几乎每一个程序员都有学习 C 语言的经历。对于初学者来说,C 语言是一个非常不错的选择。因为选择 C 语言有如下好处。(1) C 语言是 C+、Java 、C# 的基础。C+、Java 、C# 是目前最为流行的编程语言,这些语言都是建立在 C 语言基础之上的,当你学
3、了 C 语言之后,再学习 C+、Java 或 C#时会变得非常容易。(2) C 语言涵盖了计算机编程语言中的所有基础知识,对于今后学习其他编程语言和理解计算机系统的工作方式有很大的帮助。(3) 使用 C 语言编写的程序运行效率高。 C 语言是一门中高级语言,非常贴近底层,使用 C 语言编写的程序仅仅比汇编语言编写的程序运行效率低 10%20%。(4) C 语言可以直接访问内存,并可直接对硬件进行操作。普通编程者不必使用汇编语言,使用 C 语言就可以完成相同的功能。而且 C 语言要比汇编语言更加容易学习和使用。(5) 过去许多系统都是使用 C 语言实现的,如 Windows 和 Linux 操作
4、系统的大部分代码都是用 C 语言编写的,这些代码都可以得到充分利用。(6) 学会 C 语言,就为今后继续学习数据结构和算法提供了基础。因为目前绝大部分数据结构和算法教材都是以 C 语言来描述的。(7) 使用 C 语言既可以编写系统软件,也可以编写应用软件。现在的游戏软件、嵌入式开发和手机开发基本上都选择 C 语言作为开发语言。(8) 使用 C 语言编写的程序有很好的移植性。在一种计算机系统(如 IBM PC 机) 上编写的 C 语言程序,可以直接在其他系统如 DEC VAX 系统上运行。C 语言拥有如此多的优点,相信你也一定坚定了学习 C 语言的决心。接下来让我们了解一下 C 语言的特点。1.
5、1.2 C 语言的特点C 语言自从 1973 年诞生于贝尔实验室以来,经历了 40 年,却依然经久不衰、拥有最广大的用户。这是与 C 语言自身的特点分不开的。(1) C 语言程序结构规整,表达式简练、灵活,容易理解与学习。第 1 章 C 语言概述3C 语言程序结构简洁、紧凑、规整,容易阅读与理解。表达式简练,去除了一些不必要的成分,书写简单,使用起来比较灵活。因此,C 语言更加容易掌握。(2) C 语言的数据类型丰富,可以描述各种复杂的数据结构。C 语言的数据类型包括整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。其中,结构体类型和共用体类型是用户自定义的类型,根据具体需要自
6、己定义类型。C 语言所提供的数据类型可以描述各种复杂的数据结构。(3) C 语言的运算符丰富,实现复杂的运算比较方便。C 语言包含了 34 种运算符,丰富的运算符与丰富的数据类型结合,构成了多样的表达式。灵活的运算符可以很容易实现比较复杂的运算。(4) C 语言是一种结构化的语言,拥有 3 种控制语句,以函数作为程序的模块单元。C 语言适用于大型的模块化程序设计。它拥有 3 种控制语句,函数是 C 语言程序的模块单元,每个函数各自独立。C 语言的源程序可以分为多个源文件,分别进行编译,然后链接在一起构成可执行程序。这为大型软件的开发提供了方便。(5) C 语言可以对位进行操作,可以实现汇编语言
7、的大部分功能。C 语言既是高级语言,也具有低级语言的一些特征,属于中高级语言。C 语言可以直接访问内存单元,直接对位一级进行操作,可以实现汇编语言的功能。C 语言本身又是一种高级语言,可以用它来方便地开发各种应用程序。正是由于 C 语言的这种双重特性,所以常常称 C 语言为中高级语言。(6) C 语言的指针是其区别于其他语言的显著特性。C 语言中有一种非常特殊的类型 指针。指针的存在,使得它可以直接访问内存。指针使得原本灵活多样的 C 语言变得更加灵活,使编写出的程序运行效率更高。1.1.3 如何学好 C 语言在选择了 C 语言和对 C 语言的特点了解之后,要想学好 C 语言,需要把握好以下几
8、点。(1) 确立离散性思维方式,摈弃连续性思维方式。在学习计算机语言时,一定要确立离散性的思维方式,这是决定能否学好 C 语言的一个非常重要的因素。因为计算机中数据的存取是二进制形式,它是一种离散的数据表示方式。在处理类似连续性函数、积分等问题时,需要将问题转化为离散的方式进行处理。在学习 C 语言时,会深刻地体会到这一点。(2) 熟练掌握二进制与十进制、十六进制、八进制之间的相互转换。在计算机中,所有的数据都是以二进制形式存储的。而我们熟悉的是十进制,二进制数据表示起来太长,为了方便,需要将二进制转换为十进制、十六进制或八进制,这样看起来就比较直观。(3) 理解字符与 ASCII 码之间的关
9、系。通过键盘输入的数据是字符数据,而计算机是以二进制形式存储的。这需要将字符转换为对应的二进制形式并存放起来。美国国家标准学会(ANSI)专门规定了字符与 ASCII 码4跟我学 C 语言之间的对应关系。(4) 掌握运算符及运算符的优先级。C 语言提供了 34 种运算符,每种运算符都有优先级与结合性。如果有多个运算符出现在同一个表达式中,需要选择优先级别高的运算符先进行计算。如果运算符相同,则需要根据运算符的结合性进行运算。(5) 掌握 3 种程序控制结构。C 语言是一种结构化的程序设计语言,它具有 3 种控制结构:顺序结构、选择结构和循环结构。使用这 3 种结构可以解决所有的问题。(6) 掌
10、握一些常用的算法。在学习 C 语言的过程中,常常需要对一些数据进行排序及查找给定的数据,这就是排序算法和查找算法。排序算法和查找算法是在程序设计过程中常用的算法,排序算法可以分为冒泡排序、插入排序、选择排序等,查找算法可以分为顺序查找、折半查找等。掌握一些常用的算法,对今后学习数据结构和算法是大有裨益的。(7) 熟练使用指针。指针是 C 语言区别于其他编程语言的一个重要标志。指针是 C 语言的灵魂,熟练使用指针,可以使程序编写更加灵活,编写出来的程序运行效率更高。指针是一把双刃剑,使用好,可以提高运行效率,使用不当,会很容易造成难以意料的错误。因此,需要在学习的过程中熟练掌握指针的用法。(8)
11、 熟练掌握一种开发工具。要学好一门语言,就需要熟练掌握一种开发工具。只有多上机练习,才能知道程序是否正确。C 语言的开发工具有许多种,目前比较流行的有 Turbo C 2.0、Turbo C 3.0、Visual C+ 6.0、Win-TC、LCC-Win32 等。我们建议初学者可以学习 Turbo C 2.0 或Turbo C 3.0,有了基础之后可以选择 Visual C+ 6.0。Visual C+ 6.0 是一个非常专业的开发工具。说明: 目前最流行的 C 语 言版本有 Microsoft C(MS C)、Turbo C、AT&T C。1.2 进 制 转 换在计算机内部,所有的数据都是
12、使用二进制数(0 和 1)进行存储的。但是,采用二进制数表示的数字比较长、不容易记忆。因此,为了方便,通常将二进制转换为十进制、八进制或十六进制。下面就让我们来了解一下十进制数与二进制数、十六进制数与十进制数、八进制数与十进制数之间是如何进行转换的吧。首先,来了解一下十进制数的表示。1.2.1 十进制数的表示进位计数法是一种计数的方法。例如,十进制计数法就是目前最为常用的计数方法。第 1 章 C 语言概述5一个任意的十进制数可以表示为:anan-1an-2.a0.b1b2b3.bm它表示 an10n+an-110n-1+an-210n-2+.+a0100+b110-1+b210-2+b310-
13、3+.+bm10-m。其中,a i(0in)和 bj(1jm)是 09 这 10 个数字中的一个。十进制数的运算规则是逢十进一,每一位上的数字只能是 09 共 10 个数字中的一个,因此,我们称 10 为十进制数的基数。从十进制的表示公式中容易看出,每一个数字在不同的数位上代表的数值大小也不相同。例如,对于十进制数 2179,按照从右到左的顺序,第 1 个数字 9 代表有 9 个 1,第 2 个数字 7 代表有 7 个 10,第 3 个数字 1 代表有 1 个100,第 4 个数字 2 代表有 2 个 1000。我们将各位上的数字 10i 称为该位的权。每一位上的数字乘以该位的权就等于该数位上
14、的数值大小。例如,一个十进制数 36827.52 可以表示为 3104+6103+8102+2101+7100+510-1+2 10-2。在这里,该十进制数的各位的权从高位到低位依次是 104、10 3、10 2、10 1、10 0、10 -1 和 10-2。十进制数是我们日常生活中经常接触的数制,想必大家对上面谈到的十进制数并不会感到陌生吧。但是,十进制数并不是唯一的数制。例如,钟表的时、分、秒就是一种六十进制数。对于一个任意进制的数 N,用 r 表示该数的基数,那么该数 N 可以表示为:N = anrn+an-1rn-1+an-2rn-2+.+a0r0+b1r-1+b2r-2+b3r-3+
15、.+bmr-m其中,a i(0in)和 bj(1jm)是 0 r-1 个数字中的任意一个, ri 是各位上对应的权。1.2.2 二进制数的表示在计算机内部,所有的数据都是采用二进制数进行存储的。因此,很容易知道,二进制数的基数是 2,在二进制数中只包含有 0 和 1 两个数字,同时遵循逢二进一的原则。在二进制数中,各位上的权是 2k,因此二进制数 N 可以表示为:N = an2n+an-12n-1+an-22n-2+.+a020+b12-1+b22-2+b32-3+.+bm2-m例如,一个二进制数 1011.01 可以表示为:(1011.01)2 = 123+022+121+120+02-1+
16、12-2其中,(1011.01) 2 中的下标 2 表示该数是一个二进制数。十进制数是人们习惯的计数方法,而计算机内部则采用二进制数表示。为了方便,需要将十进制数与二进制数进行相互转换。二进制数与十进制数的对应关系如表 1.1 所示。表 1.1 二进制数与十进制数的对应关系二进制数十进制数0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1 1 0 0 0 1 0 0 10 1 2 3 4 5 6 7 8 9在计算机中,用二进制数表示某个数时,由于位数太长造成记忆不方便,需要将它转换为十六进制数更加方便。十六进制数的基数
17、是 16,用于表示的数字除了 09 外,还包括6跟我学 C 语言字母 A、B、C、D、E 和 F,它们用来表示十进制数的 10、11、12、13、14 和 15。八进制数的基数是 8,各个数位的数字包括 07 共 8 个数字。二进制数、八进制数、十六进制数和十进制数的对应关系如表 1.2 所示。从表 1.1 和表 1.2 中可以看出,用二进制数的 4 位数可以表示一个十六进制数,用二进制数的 3 位数可以表示一个八进制数,用二进制数的 4 位数可以表示一个十进制数。第 1 章 C 语言概述7表 1.2 二进制数、八进制数、十六进制数和十进制数的对应关系二 进 制 数十 六 进 制 数 0010
18、0100101010102345678910101010101ABCDEF八 进 制 数十 进 制 数 01234567891.2.3 二进制数、十六进制数和八进制数转换为十进制数要将一个二进制数、十六进制数或八进制数转换为对应的十进制数非常容易。将二进制数( 十六进制数或八进制数 )中的各位数乘以对应的权,然后求和,就可以得到相应的十进制数。例如,要将二进制数 101001 和 1011.01 转换为对应的十进制数,只需要将各位上的数字乘以相应的权 2k,就可以得到对应的十进制数,其转换过程如下:(101001)2=125+024+123+022+021+120=32+8+1=(41)10(
19、1011.01)2=123+022+121+120+02-1+12-2=8+2+1+0.25=(11.25)10其中,下标 2 表示该数是一个二进制数,下标 10 表示该数是一个十进制数。同理,要将一个十六进制数转换为对应的十进制数,只需要将各位上的数字乘以相应的权 16k,就可以得到对应的十进制数,其转换过程如下:(5EB)16=5162+14161+11160=1280+224+11=(1515)10(3DB.A8)16=3162+13161+11160+1016-1+816-2=768+208+11+0.625+0.03125=(986.65625)10同理,要将一个八进制数转换为对应的
20、十进制数,只需要将各位上的数字乘以相应的权 8k,就可以得到对应的十进制数,其转换过程如下:(632)8=682+381+280=384+24+2=(410)10(751.34)8=782+581+180+38-1+48-2=448+40+1+0.375+0.0625=(489.4375)10从以上内容可以看出,将二进制数、十六进制数和八进制数转换为对应的十进制数是非常简单的。那如果反过来,将十进制数转换为对应的二进制数、十六进制数和八进制数,将如何转换呢?1.2.4 十进制数转换为二进制数我们知道,一个完整的十进制数可以分为两个部分:整数部分和小数部分。要将十进制数转换为对应的二进制数,需要
21、分为两个部分转换,即整数部分的转换和小数部分的转换。 将 一 个 十 进 制 数 的 整 数 转 换 为 对 应 的 二 进 制 数 , 常 用 的 方 法 有 两 种 : 除 2 取 余 法 和降 幂法。1除 2 取余法十进制整数转换为二进制整数所谓除 2 取余法,就是将要转换的十进制数不断地除以 2,得到商和余数,并记下余数;然后将商作为新的被除数,继续除以 2,得到商和余数,并记下余数。重复以上的过8跟我学 C 语言程,直到商为 0 为止。将每次得到的余数按照先后顺序构成的 0 和 1 的序列,就是转换后的一个二进制整数从低位到高位的序列。例如,要将一个十进制数 89 转换为对应的二进制
22、数,其转换过程如图 1.1 所示。892489/2的 余 数 为 1, a0=124/的 余 数 为 , 11521202/的 余 数 为 0, a2=01/的 余 数 为 1, 315/2的 余 数 为 , a4=/的 余 数 为 0, 501/2的 余 数 为 1, a6=1(89)10=(a654a321a0)2=(0)2图 1.1 使用除 2 取余法将十进制数转换为二进制数的过程因此,将一个十进制数 89 转换后,可以得到相应的二进制数 1011001。下面我们介绍另外一种方法:降幂法。2降幂法十进制整数转换为二进制整数所谓降幂法,就是利用要转换的十进制整数不断地减去与该数最为接近的二
23、进制整数的权,如果够减,则得到减去后相应的差值,并在相应的位上记作 1;如果不够减,则直接在相应的位上记作 0。将得到的差值作为新的被减数重复以上过程,直到被减数为 0 为止。例如,要将十进制整数 89 转换为相应的二进制数,使用降幂法,其转换过程如图 1.2所示。 89 26= 89 64 = 25够 减 , 记 作 a6=125 253 不 够 减 , 记 作 a504= 25 16 = 9够 减 , 记 作 4=1923 9 8 1够 减 , 记 作 a31 =4 不 够 减 , 记 作 2=0 21 不 够 减 , 记 作 a110= 1 = 0够 减 , 记 作 0=(89)10=(
24、a654a321a0)2=(101)2 图 1.2 使用降幂法将十进制数转换为二进制数的过程在使用降幂法将十进制数转换为相应的二进制数的过程中,首先将 89 减去与之最为接近的二进制的权(即 26=64),得到一个差值 25,因为够减,将对应的位记作 1,即 a6=1。然后将 25 作为新的被减数,让 25 减去下一个二进制数的权,因为 2525(=32),所以,直接令 a5=0。接着,让 25 减去 24,因为够减,令 a4=1。按照以上方法,重复该过程,直到被减数为 0 为止。最后就得到了相应的二进制整 s 数。第 1 章 C 语言概述9以上方法是将一个十进制整数转换为相应的二进制数,那么
25、如何将一个十进制小数转换为相应的二进制小数呢?3乘 2 取整法十进制小数转换为二进制小数将一个十进制小数转换为相应的二进制小数的方法是乘 2 取整法。所谓乘 2 取整法,就是用 2 不断地乘以十进制的小数,得到一个整数和一个小数,取出整数部分,剩下小数部分;然后让小数部分继续乘以 2,得到一个新的整数和一个新的小数,取出整数部分,剩下小数部分。重复以上过程,直到余数部分为 0 或者满足一定的精度为止。最后将得到的整数部分先后排列,得到的序列就是所求的二进制小数。例如,一个十进制小数为 0.8125,转换为对应的二进制小数的过程如图 1.3 所示。如图 1.3 所示为一个将十进制小数转换为对应的
26、二进制小数的过程,这是一个正好能准确转换为二进制小数的例子。当然了,不是所有的十进制小数都能正好准确地转换为相应的二进制小数。例如,十进制小数 0.613 转换为相应的二进制小数的过程如图 1.4 所示。图 1.3 十进制小数转换为相应的二进制小数 图 1.4 按一定精度转换如果要将一个十进制数(包括整数部分和小数部分 )转换为对应的二进制数,需要使用将整数部分和小数部分分开来进行转换。例如,将十进制数 103.8125 转换为对应的二进制数需要分为如下 3 个步骤。(1) 转换整数部分:(103) 10=(1100111)210跟我学 C 语言(2) 转换小数部分:(0.8125) 10=(0.1101)2(3) 合并整数部分和小数部分:(103.8125) 10=(1100111.1101)2