第一章绪论 本章学习重点 本章介绍C语言的发展历史以及C语言的特点然后通过简单例子展示C语言的风 貌最后告诉你如何在计算机上运行C程序。 第一节C语言的产生及特点 C语言是一种得到广泛重视并普遍应用的计算机程序设计语言,也是国际上公认的最 重要的几种通用程序设计语言之一。它适合作系统描述语言,既可用来写系统软件,也可用 来写应用软件。 C语言是美国贝尔实验室的 Dennis. M. Ritchie于1972年设计实现的。C语言直接来源 于B语言但它的根源可以追溯到 ALGOL60。 ALGOL60结构严谨,其设计者非常注重语 法、分程序结构,因此对于后来许多重要的程序设计语言,如 PASCAL,PLI, SIMULA67产 生过重要的影响。但它是面向过程的语言,与计算机硬件相距甚远,不适合编写系统软件 1963年英国剑桥大学在 ALGOL60的基础上推出更接近硬件的CPL语言,但CPL太复杂, 难于实现。1967年,剑桥大学的 Matin richards对CPL语言作了简化,推出了BCPL语言 1970年贝尔实验室的 Ken Thompson以BCPL为基础,设计了更简单也更接近硬件的B语 言(取BCPL的第一个字母)。B语言是一种解释性语言,功能上也不够强,为了很好地适应 系统程序设计的要求, Ritchie把B发展成称之为C的语言(取BCPL的第二个字母)。C语 言既保持了BCPL和B的优点(如精练,接近硬件),又克服了它们的缺点(如过于简单数据 无类型等)。1973年 K. Thompson和 D. M. Ritchie用C改写了UNX代码,并在PDP-11 计算机上加以实现,即UNX版本5,这一版本奠定了UNX系统的基础,使UNX逐渐成 为最重要的操作系统之一 匚。C语言是D. M.Ritchie!72年设计实现的 图1-1展示了C语言的由来。 ALGOL (1960) (1963,剑桥大学) (1967剑桥大学, M. Richards) (1970,贝尔实验室K. Thompson) (1972,贝尔实验室D. Ritchie) 图1-1C语言的由来
C设计语言的目的是为描述和实现UNIX操作系统提供一种工具语言。但C并没有被 缚束在任何特定的硬件或操作系统上,它具有良好的可移植性。1977年出现了不依赖于具 体机器的C语言编译文本使向各种机器移植C变得更加简单,这也推动了UNX系统的 广泛实现。随着UNX的日益普及又反过头来带动了C语言的迅速推广,使它先后被移植 到各种大、中、小、微型计算机上。 1978年,贝尔实验室的Bin.w. Kernighan和 Dennis. M. Ritchie((合称K8R)合著了 《 The C programming language》-书,并在附录中提供了C语言参考手册,这本书成为以后 广泛使用的C语言的基础,被人们称作非官方的C语言标准。1983年美国国家标准化协会 (ANSI)开始制定新的标准,这就是 ANSI O标准。1990年,C语言成为国际标准化组织 ISO通过的标准语言。 C语言是作为描述系统的语言而设计,但随着其日益广泛的应用特别是80年代以后 各种微机C语言的普及,它已经成为众多程序员最喜爱的语言它的使用覆盖了几乎计算 机的所有领域包括操作系统、编译程序、数据库管理程序、CAD、过程控制、图形图象处理 等等。 C语言如此成功是有其自身特点的: 1C语言是比较“低级的”语言 有人把C语言称为“高级语言中的低级语言”,也有人称它是“中级语言”。这样说不起 它功能差或难于使用,而是指它具有许多通常只有象汇编语言才具备的功能,如位操作 直接访问物理地址等等,这使C语言在进行系统程序设计时显得非常有效,而过去系统软 件通常只能用汇编语言编写。事实上,C语言的许多应用场合是汇编语言的传统领地,现在 用C来代替汇编,使程序员得以减轻负担、提高效率,而写出的程序具有更好的可移植性。 C语言具有更多的接近硬件操作的功能而不提供直接处理复合对象,如作为整体看待 的字符串、数组等的操作,这些较高级的功能必须通过显式调用函数来完成。这看起来是个 缺陷,但这使语言的规模较小,更容易说明,学习起来也快。比如说,C语言只有32个关键 字,而一些微机上的BASC,关键字多达100个以上。 2.C语言是结构化的语言 C语言在结构上类似于 ALGOL60、 PASCAL等结构化语言。这大概与它源于ALGO L60以及60年代末70年代初结构化程序设计方法的兴起有关。C语言的主要结构成分是 函数——C的子程序。函数允许一个程序中的各任务分别定义和编码,使程序模块化,在函 数的外部只需了解函数的功能,而将实现的细节隐藏起来设计得好的函数能够正确地工作 而对程序的其他部分不产生副作用C语言还提供了多种结构化的控制语句如用于循环的 for, while do-while i句,用于判定的eewh句等以满足结构化程序设计的要求。 3.C语言是程序员的语言 看到这个提法,你可能会奇怪:难道还有不是程序员的程序设计语言吗?确实有许多程 序设计语言不是为专业程序员设计的,比如说: FORTRAN是为工程师, COBOL是为商业 人员, PASCAL是为学生,而BASC是为非程序员设计的。C是为专业程序员设计的语言 Ritchie是专业程序员,而C最初是为了他自己写UNX操作系统而设计的。C语言实现了 程序员的期望:很少限制,很少强求程序设计自由度大,方便的控制结构,独立的函数,紧凑 的关键字集合和较高的执行效率。用C编写程序可获得高效的机器代码,其效率通常只比
汇编语言生成的机器代码低10~20%,而同时C又具有 PASCAL那样的结构,这就难怪有 大量的程序员喜欢它 C语言的语法限制不太严,例如,对数组下标越界不做检查整型字符型数据可以通 用,不专设逻辑型数据而以整型来代替等。较少的限制给程序员带来较大自曲这就要求程 序员在编程时应确实明白自己在做什么,而不要把检查错误的工作仪寄托于编译程序。当然 这会带来一些麻烦但作为程序员应该考虑好再开始编码。其实有时懊让计算机惩罚一下 粗枝大叶的程序员也不一定是什么坏事 C语言得到广泛使用的主要原因可能就是因为程序攒善欢它回但不是专业夫员的 专利非专业人员经过实践也会熟练地掌握它现在有许多不同专业的非计算机专业大员正 在使用或正在转向C语言。C语言是我们大家共同的财富 第二节用C语言编写程序 学习一种程序设计语言唯一的有效途径就是用它编写程序。下面几个简单的程序将带 你进入C的世界,开始我们的学习。 第一个程序总是输出一个字符串这里,选择著名的"hlo,word"程序,以表示对 K8R的敬意 例1.1 printf hello, world \n"); 这个程序的运行结果是输出字符串 hello, world 上面的程序称C语言源程序简称C程序。为了让它运行,必须先找一个编辑程序输入 它然后编译,装入,最后执行 现在让我们来看看程序本身。main是一个函数名,表示“主函数”。一个C程序,不管简 单或复杂,总是由一个或多个函数组成由这些函数实现要做的操作。函数名可以按照你的 喜好去取但main是一个特殊的名字。C程序总是从man函数开始执行这意味着,一个程 序必须在某个地方有一个main函数 花括号}括起构造函数的语句称函数体。函数体中只有一条函数调用语句 printf(("hl, world\n”) 其功能是将双引号”中的内容输出。 printf是C语言中的库函数,它来自计算机厂家提供的 输入输出库你可以直接去调用它。双引号中的内容是调用prnt时提供的参数,表示为 个字符串。字符串中的是C语言中的换行字符在输出时它将终端的光标移动到下一行 的开始。如果不使用\n,输出时就会发现光标停在输出字符串的后面。prin不提供自动换 行的功能每当在程序中需要执行换行操作时都必须写出\n。例如,我们把例1.1改写一 下
aino printf("hello, ")i printf("n") 执行结果也是一样的。如果要将程序改成 printf ("hello, n"); printf ("world \n"); 你会发现输出变为: world 在这里我们可以看到C语言倾向于把怎样处理的权利交给程序员。 prit语句的最后跟着一个分号“,”,它表明一个语句的结東。 例 1.2 /*求两个整数之和*/ int a, b, sum i sum =a+bi printf("sum is %d n", sum); 本程序的功能是求两整数之和。/*…*/部分是注释是为了便于阅读程序而安排的, 对程序的编译和执行没有影响。注释可以加在程序的任何位置。注释可以是任意一串字符, 但不能再含有/*…#/,也就是说注释是不能嵌套的(也没有必要)。这里的注释是用汉字 给出的,你的计算机可能没装汉字可用英文或汉语拼音来写注释。本书中采用汉字注释完 全是为了阅读的方便。 程序中的 int a, b, sum t 是变量定义部分,这里我们用int定义变量a、b和sum为整型。C语言规定使用任何变量之 前都要先定义
sum =a+b 是三个赋值语句,“=”是赋值运算符它的作用是把其右部表达式的值赋给左部的变量,这 里是把值12赋给变量a,把值34赋给变量b,把a+b的结果赋给变量sum。 printf("sum is %d n", sum 中的"sumi和”m"我们已经熟悉,%d是一个输出转换说明意思是输出时用一个整型值 来代替它这里,这个整型值是变量sum的值。于是本程序的输出结果为: sum is 46 例1.3 main()/*求两个数中较大者*/ int a, b printf("a,b=)i scanf(m%d, %d",&a, &b)i c=max(a, b) printf ("max=%d\n",c); Int max(a,b)/*返回x、y中较大者* x,yi Int Z if(x>y) return(z)i 本程序定义了两个函数:main和被调函数max。在main中,语句 printf("a,b=m) 输出 然后光标停在=之后。下一句 scanf("%,%d",8a,&b); 用于接收两个整型数据到变量a和b中, scanf是c输入输出库中提供的输入函数,它要求 按照转换字符(这里是%d表示整型)将相应类型的数据输入到指定变量的存储单元中去, 8a表示取变量a的地址。 语句 c= max(a, b);
是将函数max的值赋给变量c,其中a和b是参数(称为实在参数),执行时将变量a和b的 值传给被调函数max。max的作用是将x、y中较大的数送z,并通过语句 将其作为函数值返回给主调函数。函数头 封tx,y; 表示max带有两个形式参数x和y,在max被调用时,这两个参数的值由主调函数中对应 的实在参数(本程序中是a和b的值)传过来,函数体中求出x、y中较大的数值送乙,并返回 主调函数,语句 if(x> y 是C中的一种判定控制语句结构,它根据x是否大于y来选择执行 本程序的执行情况如下 max=6 例1.4 # include Stdio. h" maino while((c= getchar())!= EOF putchar(c); 这个程序的功能是将输入的内容复制到输出第一行 #t include "stdio h" 是C语言中的文件包含 stdio. h是一个头文件,通过文件包含命令# include,程序把si.h 包含在自己所在的文件中。stdo.h是关于标准输入输出的头文件,其中包括使用标准输入 输出库函数的许多信息。在本程序中,由于使用 getchar和 putchar函数(实际上是宏,将在 第九章中介绍),因此需要用命令包含将存有必要信息的 stdio. h包含进来。符号EOF也在 stdio.h中定义,实际中,它定义为 define eof-1 意思是在程序中遇到EOF就用-1代替EOF是文件结束标志,对于任意一个文件,系统会 自动在其尾部加一个EOF标志。当文件是从键盘上输入时,在微机DOS操作系统下,打入
z(ctr+z)后,系统自动为输入流加上一个EOF(UNX系统下,可打入^d)。函数 getchar 用于读一个字符, putchar用于输出一个字符,语句 while表示当括号内的表达式值为真时 反复地执行后面跟着的语句因此 hile((c=getchar O)!=EOF) putchar (c); 的意思是:当读入的字符不是EOF时,就输出它直到读入EOF,所以我们可以这样运行这 个程序 abc1234xyz789^z(输入) abcl234xyz789(输出) 在本章的例子中,我们让每个语句单独占据一行的位置,并且书写时作了适当的缩进, 这些都不是C语言语法所要求的,而是为了阅读方便如例1.4也可以写成 # include“ stdio.h main(lint ci while((c=getchar())!=EOF)putchar(c); I 其结果也是一样的。C语言不是靠回车,而是靠分号来标识一个语句的结束,回车的功能与 个空格是相同的。虽然可以把程序写成上面那个样子,而且可以正确地执行,但实际中几 乎没有人那么写即使是很短的程序。计算机界有句名言:程序是给人读的。看到这个命题, 你也许会奇怪,程序不是为了在计算机上运行的吗?确实如此,但不仅仅如此,你写一个程序 以后可能要修改别人也可能会阅读或修改你的程序,在没有完全读懂的情况下做修改,将 会带来许多麻烦即使不改,一个表达清楚的程序也会给人带来愉快。再者连你自己都不能 清楚地表达思路的话,还能指望计算机作什么呢 为了清晰而正确地写程序,首先要使程序具有良好的结构如使用将实现细节隐蔽得很 好的函数,少用外部变量,不采用非结构化的控制结构等。同时,也要注意书写风格如每个 语句独立占一行,适当的缩进尽量选择有实际意义的标识符,适当的加入注释等等,这些在 我们今后的讨论中还会反复提到。总之,从一开始写程序就要培养好的风格 第三节C程序上机运行 学习编程,上机是非常重要的。在计算机上编程并运行,从结果中了解程序的运行过程 进而了解程序的结构,比只看书要有效得多。另外,你可以对已有的程序做各种修改进而了 解语言更多的知识,也可以向别人学到很多东西。上机可以提高你编程的兴趣,也可以提高 自信心,当看到自己编写的程序在计算机上正确地运行时,你会感到自己的创造力 本节中,我们介绍 turbo C上机的简单步骤如果你使用其他的C,或希望对 turbo C 有更多的了解请参考相应的用户手册 用 turbo C上机的步骤: 先将 turbo C软件安装到机器的硬盘上。 调入 turbo C 只要打入te,然后回车,屏幕顶部将显示出 turbo C的命令菜单(见图1-2)
FILE EDIT RUN COMPILER PRLJECT OPTIONS DEBUG 图1-2命令菜单 用键盘上的“←”和“→”键可以移动屏幕上的光标如果光标不在顶部的命令菜单行中 可以打F10键将光标移到顶部。将光标移到“FLE”处,打回车键FLE下面出现一个子菜 单,如图1-3,用“↓”键将光标移到Load(或New)处打回车键表示要输入源程序,屏幕上又 出现一个小窗口如图1.4所示要求你输入文件名,此时可打入 filel.c 如果原来没有这个名字的文件,将建立一个新文件如果已有此文件则将此文件调入并在 屏幕上显示,然后自动转为编辑(EDT)状态。 FILE EDIT RUN COMPILER PRLJECT OPTIONS DEBU Pick Alt-f3 Write to Quit Alt-x 乙 甲 图1-3子菜单 Load File Name file l. c 图1-4文件名输入框 你也可以直接进入编辑状态,这时在DOS命令行中打入 tc filel 系统就自动进入编辑屏幕。也可不打c,这时系统取缺省值.c。 2.编辑源文件。 你可以根据需要输入或修改源程序。 3.编译源程序 只需要简单地打F9键就可以进行源程序的编译和连接,并在屏幕上显示有无错误 如有错误按任一键后屏幕显示源程序,光标停在出错的位置上。屏幕的下半部分将显示出
有错误的行和错误原因。根据提供的信息可以修改错误,这时按下“F6”键后就可修改错误, 修改完后再按“F6”键,接着打“、”键,光标就停到下一个出错的行。所有错误修改完后,再 按“F9”进行编译,如此反复,直到没有编译错误为止 4.执行程序 你只要打入^F9(按下ctrl键的同时按F9键)即可执行程序。如果程序中需要输入数 据,就在此时将所需数据输入,接着程序执行,输出结果 如果发现结果不对,可再按步骤23、4修改程序、编译执行程序直到得到正确的结 5.保存文件 编辑完源程序或准备退出 turbo C时,也可打“F2”键将源程序存在硬盘上 6.退出 turbo C 同时按下A和X键,便退出 turbo C回到操作系统命令状态。此时可以用系统命令 来显示源程序或运行程序。如 type filel.c↓(显示源程序清单) fill↓(执行程序 file l. exe 如果想再输入或修改源程序,可以再从步骤1开始。 以上的步骤是对一个程序只放在一个源文件中时采用的,如果一个程序放在多个文件 中,就要使用 PROJECT项生成所谓pri文件。考虑到初学时程序通常都较小,不必放在多 个文件中分别编译,这里就不多介绍了 最后讲一下本书附带磁盘的使用方法。本书中全部例子的源程序附在一张磁盘上,文件 名是字母E开头后跟章、例号,如例1.1为 E1-1.c 你可以直接调入 turbo C编译并执行这些例子,有些例子有多个程序,这时文件名中再含有 个标识版本的数字放在最后如例1.1有两个版本的话程序名分别是 和 E1-1-2. 书中有些例子只给出了一个被调函数,而没有maim,为了便于上机操作盘中都给了用 于测试这些例子的主调函数,上机时也可以直接编译
第二章数据类型、运算符与表达式 本章学习重点 本章介绍C语言的基本数据类型:整型浮点型、字符型相应类型的变量和常量以及 类型之间的转换,并介绍算术赋值和逗号表达式的慨念和使用。通过本章的学习应能掌握 C语言数据和运算的基本概念,为以后各章的学习打下基础 第一节C语言的数据类型 许多人总爱形象地把计算机程序与做菜用的菜谱做个类比。确实如此,菜谱中规定了厨 师烹饪的步骤就象计算机程序中一条条指令规定了计算机应怎样运行。菜谱中的指令总是 把各种食品原料当作自己操作的对象,而计算机中要被处理的对象就是数据 图21给出了C语言中所能处理的各种数据类型。 本类型双精度浮点型( double) 字符型(char) C语言的数据类型 构造类犁 联合( union 枚举(enum) 针 图2-1数据类型 在本章中我们介绍基本数据类型而其他数据类型留在后面章节中讨论。 第二节标识符 标识符是一个字符序列,在C语言中用来标识常量、变量、函数数据类型的名字。C语 言规定:标识符只能由字母、数字及下划线“”(不是减号)组成并且数字不能做为标识符 的第一个字符,下面是一些合法的标识符 Num of_ lin