第 1章初识 C语言 本章学习目标 了解 C语言的发展历程和特点 学会搭建 C语言开发环境 了解 C语言的编译过程 熟悉 C程序代码的基本架构 本章先介绍 C语言的发展史,然后介绍 C语言的语言特点,昀后介绍 C程序的编译过程和用于 C程序的集成开发工具。 1.1 C语言的发展史 千里之行,始于足下。马上要开始 C语言的旅程了,突然想起我还是初学者的时候,曾经翻阅了大量的 C语言入门书籍,千篇一律,都是在刚开始的时候讲解一些概念、理论和很多的术语。而我自小喜欢数理化,对文科不感冒,尤其是对需要大量死记硬背的知识感到非常头疼。所以看着这些概念、理论、术语,没多久就会有头昏眼花、想睡觉的感觉。结果是大部分的内容都如过眼云烟,随风而去了,不过有两点倒是奇迹般地记在脑海中了,到底是哪两点呢? 第一点是 C语言的创始者。中国有句老话是“吃水不忘挖井人”,既然决定学习 C语言了,怎么能不知道 C语言的创始者是谁呢?好了,直接告诉你,是来自贝尔实验室的丹尼斯·里奇 (Dennis Ritchie),美国人,生于 1941年。他在 1972年发明了 C语言,被尊称为 C语言之父。但非常遗憾的是, 2011年 10月 12日他永远地离开了我们,图 1.1是丹尼斯·里奇的照片。 图 1.1丹尼斯·里奇 第二点是 C语言的标准。为什么非要了解 C语言的标准呢?其实不难理解,想想当年秦始皇统一中国后,为何立即进行了“书同文,车同轨,统一度量衡”的改革?因为只有使用同一种文字、同样的尺度、同一种标准,才能让国人彼此看得懂,交流更方便,才能更好地促进社会的发展。同样如此, C语言不是给一个人使用的,其使用者包括大量的开发者、维护者、管理者,以及 C语言编译器的实现者,如此多的使用者,如果没有统一的标准遵循,你这么写,他那样用,结果就是你写的东西他看不懂,他写的东西你也看不懂,那将是多么的可怕。有了标准之后,大家都按同一标准干活,就非常便于大家交流,从而推动了 C语言更快更好地发展。好了,下面就来学习一下 C语言的这些标准。什么?这些标准?是的,没有事物是一成不变的, C语言从诞生到现在已过了半个世纪,随着 C语言的不断发展,经历了以下几个标准制定时代。 1.“K&R”标准 1978年,丹尼斯·里奇与布莱恩·科尔尼汗联合出版了名为《 C程序设计语言》(The C Programming Language)的著作,这本书被 C语言开发者称为“ K&R”,很多年来被当作 C语言的非正式的标准说明,人们称这个版本的 C语言为“ K&R C”。 2.“C89”标准 C语言于 1972年 11月问世, 1978年由美国电话电报公司( AT&T)贝尔实验室正式发布。 1983年,美国国家标准局( American National Standards Institute,ANSI)开始制定 C语言标准,并于 1989年 12月完成,在 1990年春天发布,该标准称为“ ANSI C”标准,也称为“ C89”标准。 3.“C90”标准 后来 ANSI把“C89”标准提交到 ISO(国际化标准组织), 1990年被 ISO采纳为国际标准,称为“ ISO C”标准。又因为这个版本是 1990年发布的,因此也被称为“ C90”标准。 4.“C99”标准 在“C89”标准确立之后, C语言的规范在很长一段时间内都没有大的变动。直到 1995年 C程序设计语言工作组对 C语言进行了一些修改,成为后来在 1999年发布的 ISO/IEC 9899:1999标准,通常被称为“ C99”标准。 5.“C11”标准 2007年,C语言标准委员会又重新开始修订 C语言,到了2011年正式发布了ISO/IEC 9899: 2011标准,简称为“ C11”标准。 读者可能有些疑惑,这么多标准,到底该用哪一个呢?其实“ K&R”是非正式标准,而且年代久远,现在基本不用了; “C89”和“C90”属同一个标准,即它们内容一致,只是在不同的时间被两家不同的机构认证罢了,这个标准一直用到现在;目前的主流应该是 “C99”标准,现在已开始渐渐向这个标准过渡,不过仍有某些编译器对这个标准支持得不够好,所以用的时候还要注意一下; “C11”是现行昀新的 C语言标准,但还没有完美支持 的编译器。本书采用的是 GCC编译器,其中一个原因就是它对“ C99”标准的支持相对较好。至于什么是编译器?别急,后面的章节会讲到。 1.2 C语言的特点 1.2.1 结构化程序 什么是结构化程序?先来回想一下现实中盖楼的步骤,首先由设计单位设计图纸,然后建设单位拿到图纸后开始组建各个业务部门来承建工程(例如材料部负责购置建设工程所需的各种材料,工程部负责楼体的建造,监理部负责质量的监督等),而各个部门又会对所属的工人进行分工(例如工程部的工人中有负责抬钢筋的,有负责和泥沙的,有负责浇铸的,有负责砌墙的,有负责开吊机的等)。各个部门的工人们齐心协力、有条不紊地辛勤劳作,昀终才能一点一点按照图纸把整座大楼建设完成。其实结构化程序的开发也是如此,首先按照用户的需求进行细致的设计,形成程序的总体框架,然后根据框架的要求,逐步细化出各个业务逻辑,再将各业务逻辑分解为许多模块单元,昀终由这些模块单元搭建出整个程序。这种把一个庞大而复杂的问题,经过不断细化分解,昀终形成许多简单模块单元的设计思路就是结构化程序设计的思想。现在有点感觉了吧? 用 C语言编写出来的程序属于结构化程序,即 C语言程序设计就是结构化程序设计,结构化程序设计的概念昀早由 E.W.Dijikstra在 1965年提出,它的主要观点是采用自顶向下、逐步细分和模块化的程序设计方法,使用顺序、选择、循环三种基本控制结构来构造程序。 所谓自顶向下就是要求在程序设计之初要高瞻远瞩、总揽全局,不要太关注旁枝末节,先把程序的主体框架确定下来;逐步细分就是在主体框架确定之后,根据不同的职能划分出不同层次的业务逻辑;模块化就是针对某个业务逻辑制定出一系列具体的实现步骤。所有的模块全部完成之后,整个程序也就基本完成,剩下的就是对这些模块像搭积木一样进行相应的拼装和调试。 1.2.2 C语言的优缺点 C语言从诞生到现在,已经历了半个多世纪,依然受开发者的青睐,显得生机勃勃,在各个领域被广泛使用,这足以证明 C语言的重要性和优越性。那么 C语言到底有着什么样的优点呢? 1. 简洁性 C语言一共只有 32个关键字和 3种基本控制结构,可通过简短的代码实现模块,并对模块加以整合,从而构建出一个庞大复杂的程序。整个程序由不同的模块相互调用、配合,就像人体内的脉络一样,猛一看好像一团乱麻,仔细分析却又十分清晰。同时,这也给程序的调试带来好处,发现问题后,可寻着脉络到相应的模块中去查找,提高了程序开发、维护和调试的效率。 2. 灵活性 C语言程序书写形式自由,语法限制不太严格,程序设计自由度大。 C语言能通过简单的整数类型、实数类型和字符类型,灵活地构造出更加复杂的数组、指针、结构体、联合体等复合数据类型,并以此实现链表、队列、栈、树、图等各种数据结构。尤其是 C语言中可以使用指针,通过指针直接寻址到相应的内存单元,即可对内存的数据进行访问、修改等操作,从而编写出非常灵动、奇妙的 C语言程序。 3. 高效性 程序设计语言可以分为机器语言、汇编语言和高级语言,机器语言是使用 0和 1的二进制码书写的语言,由于计算机能直接识别这种语言,所以使用机器语言编写的程序执行效率非常高。但是,机器语言对于人类来说阅读性极差,直接用机器语言来进行程序设计更加困难,例如一串二进制码“ 1000011100010100…11001011”,很难看出这是两个整数相加的意思,所以后来产生了汇编代码,它把二进制码中某些具有特殊功能的一块代码串用一些助记符的方式来表达,例如“ add ax,bx”,这样使得人类对程序代码的理解变得相对容易。高级语言中使用了和人类昀为接近的语言方式来表示,例如“ 1 + 2”,从这里就能直观地感受到使用高级语言的方便之处。 用 C语言编译生成的目标代码质量和执行效率仅比用汇编语言编写的程序低一些,但相比使用其他的高级语言( C++、Java、C#等)编写出的程序要高。 既然 C语言有如此多的优点,那它有没有什么缺点呢?其实就像世间万物一样,都有两面性,就好比一把双刃剑,用得好就是杀敌的利器,用不好反而会伤到自己的身体。同样,C语言的这些优点,如果运用得不好就会变成它的缺点,例如整体设计欠缺,算法逻辑混乱,标识命名不得体,代码编排不规范,使用了野指针,出现内存泄漏等,就会使 C语言程序失去原有的简洁、灵活和高效,变成一个糟糕的程序。 1.3 C语言的发展方向 学好C语言之后能做什么?应该朝哪个方向发展?这通常是 C语言初学者昀为关心的问题。突然想到了我还在上小学时,老师会经常在班上问:“同学们,长大了以后想做什么?”,全班几乎异口同声地回答:“我要当科学家! ”。后来真正成为科学家的好像一个也没有。但这不是一件令人遗憾的事情,虽然没有成为科学家,但通过认真的学习,有的做了老师,有的做了警察,有的拥有自己的企业,还有的成为了作家(不是说我啊!哈哈哈)。聊这件事的目的是想让读者知道,今后想干什么与今后真正干了什么并不能画上等号,唯有认真地学习,拥有了知识和技术,才拥有更广阔的发展空间。 下面就来谈一谈 C语言的本领。 当然从 C语言所拥有的简洁、灵活、高效的特性上,就能看出 C语言在系统开发、底层设计上有着卓越的表现。更直接的例子就是我们天天使用的操作系统、数据库、游戏引擎等大多是使用 C语言实现的,很多经典算法、框架也是用 C语言来编写。使用其他高级语言在某些功能上遇到“技术瓶颈”的时候也会用 C语言来解决。还有就是现在已经进入了“物联网”时代,嵌入式开发已经非常广泛,学好 C语言也是为嵌入式开发打基础。或许还有一些读者准备在学完 C语言后,继续学习其他的基于面向对象思想的语言,那学好 C语言也是非常重要的,毕竟不懂得结构化的程序设计(面向过程的),又如何真正理解面向对象的思想呢。 现在是不是认识到 C语言的厉害之处了,下面就赶紧来看看使用 C语言开发需要什么样的开发环境吧。 1.4 C语言开发环境 1.4.1 C语言的编译器 好了,现在编译器“粉墨登场”了。编译器是干什么的呢?它其实就是个“翻译官”,能将 C语言翻译成机器语言。计算机的 CPU(中央处理器)只能识别和运算二进制码(由 0和 1组成的代码,称为机器语言)。而用户想要和计算机交流,只能使用二进制码与其对话,例如早期的计算机没有键盘这样的输入设备,开发者们使用带孔的纸质长带与计算机交流,其中有孔部分表示 1,无孔部分表示 0,一个程序需要使用很长的一条纸带,上面布满了密密麻麻的孔位,一旦有孔位打错,就前功尽弃,需重新制作。可想而知是多么的麻烦。同时,也必须向早期的开发者们致敬,他们的细致与敬业精神让我们无比钦佩。 值得欣慰的是,现在有了键盘这样的高级输入设备,使开发者摒弃了制作带孔纸带来与计算机交流的痛苦方式。但是使用二进制又会方便吗?例如想让程序能够计算 1和 2的和,对着计算机大喊或者用键盘输入一句话:“请告诉我 1加 2等于几?”,计算机是不会有反应的。不过这不能怪它,因为它根本不知道我们的用意,更确切地说是它不懂我们的语言,它只认识二进制码,所以我们只能把这句话或文字以二进制的方式告诉它。如何把我们的文字变成计算机能认识的二进制码,这就得靠编译器来帮忙了。 对 C程序如何工作的认识有点清晰了吧?我们平常说的用的都是人类语言,把人类语言用 C的标准来规范和书写后就成了 C的程序语言( C语言),然后通过编译器把 C语言翻译成计算机所能识别的机器语言,这就是为什么说编译器就是一个“翻译官”了。 那么编译器是不是就一个呢?也不是,从 C语言诞生至今,出现了许许多多的编译器,这些编译器在不同的时间由不同的厂家和公司以及开发者个人实现出来,其中昀主要的、比较流行的和使用比较广泛的就三类: TC、MS C和 GCC。 TC是 Turbo C的简称, Turbo C是美国 Borland公司的产品,该公司在 1987年首次推出 Turbo C 1.0 产品。不过现在使用 TC的开发人员较少,没有下面的两个使用广泛。 MS C是 Microsoft C的简称,它是鼎鼎大名的美国微软公司的产品,不过它一般都是在集成开发环境( IDE)中来使用, MS C很好地支持 C89和 C90标准,但对 C99标准的支持还不够完美。 GCC是 GNU C Compiler的简称,GNU是一个自由的操作系统,其内容软件完全以自由、开放的方式发布。 GCC原本作为 GNU操作系统的官方编译器,现已被大多数类 UNIX 操作系统(如 Linux、BSD、Mac OS X等)采纳为标准的编译器, GCC同样适用于微软的 Windows操作系统。同时,由于它对 C99标准支持得比较好,所以特别适合 C语言爱好者 来学习和使用。本书采用 GCC作为案例的编译器。 1.4.2 IDE开发环境 有不少初学者在学习编译器时,会被编译器、编辑软件以及集成开发环境( IDE)搞 得晕头转向。下面就来帮大家理一理,例如要编写一个 C语言程序,就必然要书写代码, 那么代码在哪里书写呢?这时就需要一个文本编辑软件。例如在 Windows系统中新建并打 开一个记事本,然后就可以在这个记事本中进行代码的书写。书写完成保存之后,就得到 一个 C程序的源文件。但这个源文件不能在计算机中执行,我们还得借助编译器对这个源 文件进行编译,才能形成计算机所能识别的二进制码(机器语言),这时才能在计算机中 执行。所以要想得到并运行一个可执行的 C程序,得经过三步:①在编辑软件中编写代码, 得到 C的源文件;②使用编译器对源文件进行编译,得到可执行文件;③双击可执行文件, 让程序在计算机上运行。 那么集成开发环境( IDE)又是干什么的呢?简单地说,它就是把上面的三步合并在 一起,把代码的编辑、文件的编译以及昀后的文件执行全部集成起来。通过简便的操作就 能自动地完成三步操作,这样就极大地方便了程序的开发。集成开发环境往往还带有调试 的功能,如果程序的运行结果出现错误或异常,可以轻松地对源文件中的代码进行定位和 跟踪。 那 IDE又有哪些呢?例如基于 TC编译器的 Turbo C 2.0,基于 MS C的 Visual C++、 Visual Studio系列,基于 GCC的 CFree、CodeBlocks、Dev C++,使用在苹果系统里的 XCode等,这些都是集成开发环境。 但是,本书所采用的开发环境却是 Windows + 记事本 + GCC编译器。为什么没有使 用集成开发环境?原因有三点:①我们是学习 C语言的,而不是学习集成开发环境的,要 把精力更多地投入在对 C语言的学习上,通过手工输入编译命令、调整编译选项,可以让 读者更了解程序的编译处理过程,而且使用 GCC编译器可以更好地兼容 C99标准。②虽 然使用集成开发环境能大大提高程序的开发效率,但对初学 C语言的人来说未必是好事, 例如集成开发环境所提供的代码自动补全和纠错功能,会造成对语言细节的疏忽,对集成 开发环境形成高度的依赖,离开了集成开发环境,就不会写代码了或者写出来的代码错误 百出。③软件体积小,对机器的配置要求不高,不论大家的机器配置如何,都可以满足这 样的 C语言开发环境要求。 现在就开始动手搭建我们的开发环境吧。首先是编辑器,本书使用的是 Notepad++(官 网地址为 https://notepad-plus.en.softonic.com/),它是一个开源和免费的文本编辑软件(俗 称加强版的记事本),下载和安装都非常简单,本书所使用的是 V7.7 32位的版本,界面如 图 1.2所示。 下面开始安装编译器,为了在 Windows上安装 GCC,我们进入 MinGW的下载页面(https://sourceforge.net/projects/mingw/files/),单击右侧 “Recommended Projects”的 “MinGW-w64 - for 32 and 64 bit Windows”链接,下载昀新版本的 MinGW 在线安装程序。 下载完成后,双击该文件进行安装。图 1.3~图 1.8为 GCC安装的详细过程。图 1.2 编辑器 Notepad++ 如图 1.3所示,进入 MinGW安装界面,单击 Next按钮。 图 1.3 MinGW在线安装的首界面 图 1.4所示为 MinGW的设置界面,当前安装的版本为 8.1.0,单击 Next按钮进行下一步。 图 1.4 MinGW的设置界面图 1.5所示为安装路径选择界面,选择路径后单击 Next按钮。 图 1.5 安装路径界面下载安装文件界面如图 1.6所示,开始联网下载文件,需保持网络畅通。 图 1.6 下载安装文件界面图 1.7为安装文件下载完成界面,下载完成后单击 Next按钮。 图 1.7 文件下载完成界面 软件安装完成的界面如图 1.8所示,单击 Finish按钮完成软件的安装。为了后面开发时能更方便地使用 GCC,在安装完成后,我们还需配置 Windows系统的环境变量。图 1.9~图 1.13为环境变量的配置过程。在桌面的计算机文件夹处右击,在弹出的快捷菜单中选择“属性”菜单项,弹出 图 1.8 安装完成界面 如图 1.9所示的窗口,单击窗口左侧的高级系统设置项,弹出如图 1.10所示的“系统属性”对话框。 图 1.9 “系统属性”对话框 在图 1.10中单击“环境变量”按钮,弹出如图 1.11所示的“环境变量”对话框。在“环境变量”对话框中单击“新建”按钮,弹出如图 1.12所示的“新建用户变量”对话框,在其中对变量名和变量值进行设置,变量名为 PATH,变量值为 GCC安装目录中