1.4 C语言的初步知识
1.4.1 C语言的起源与发展
C语言诞生于1972年,由美国电话电报公司(AT&T)贝尔实验室的D.M.Ritchie设计,并首先在一台使用UNIX操作系统的DEC PDP-11计算机上实现。
C语言是在B语言的基础上发展起来的,早在1970年,美国贝尔实验室的K.Thompson就以BCPL语言(Basic Combined Promgramming Language)为基础,设计出一种既简单又接近于硬件的B语言,并用它编写了第一个UNIX操作系统。而BCPL语言是英国剑桥大学的Matin Richards于1967年基于CPL语言(Combined Programming Language)提出的一种改进语言。CPL语言又是英国剑桥大学于1963年根据ALGOL 60 推出的一种接近硬件的语言。由此可见,C语言的根源可以追溯到ALGOL 60,其演变过程如下:
ALGOL 60(1960年)→CPL(1963年)→BCPL(1967年)→B(1970年)→C(1972年)
C 语言问世以后,在应用中多次进行了改进。1973年贝尔实验室的 K.Thompson 和D.M.Rithie用C语言将UNIX系统(即UNIX第5版)重写了一遍,增加了多道程序设计功能,使整个系统,包括C语言的编译程序都建立在C语言的基础上。第5版UNIX系统(UNIX V5)奠定了UNIX系统的基础。到1975年,UNIX第6版问世。随着UNIX的巨大成功和被广泛移植到各种机器上,C 语言也被人们所接受,并移植到大型、中型、小型和微型机上,它很快风靡全世界,成为世界上应用最广泛的计算机程序设计语言之一。
1978年又推出了UNIX第7版,以该版本中的C语言编译程序为基础,B.W.Kernighan和D.M.Ritchie合作(被称为K&R)出版了“The C Programming Language”一书。该书介绍的C语言被称为标准C,这本书成为后来被广泛使用的C语言的基础。1983年,美国国家标准化协会(ANSI)对C语言的各种版本做了扩充和完善,推出了新的标准,被称为ANSI C,它比原来的标准C有了很大的改进和发展。1987年,ANSI又公布了87 ANSI C新版本。目前流行的各种C语言编译系统都是以87 ANSI C为基础的。在微机上使用的C语言编译系统多为Microsoft C、Turbo C、Borland C和Quick C等,它们略有差异,但按标准C书写的程序,基本上都可运行。读者要了解不同版本的编译系统的特点和规定可参阅有关手册。
1.4.2 C语言的特点
C 语言之所以成为世界上应用最广泛、最受人们喜爱的计算机高级语言之一,与它本身所具有的突出的优点是分不开的。C语言的主要特点概括如下。
① 语言简洁、紧凑,使用方便、灵活。C语言一共只有32个关键字,9种控制语句。程序书写形式自由,主要用小写字母表示。
② 支持结构化程序设计。C语言具有结构化的控制语句,以函数作为程序的模块单位,这使得它可以很方便地实现这种构造。
③ 运算符丰富。C语言除了拥有一般高级语言都有的运算符外,还拥有不少独特的运算符,可以实现其他高级语言不能实现的运算,增强了C语言的运算功能。
④ 数据类型丰富。C 语言能方便地实现各种复杂的数据结构,具有很强的数据处理能力。
⑤ 较强的编译预处理功能。C语言的编译预处理功能,为开发规模较大的程序提供了方便,极大地提高了程序开发的效率。
⑥ C语言的可移植性好。C语言本身只需稍加修改便可用于各种型号的计算机和各类操作系统,因此,用C语言编写的程序也可以很方便地用于不同的系统,这也是C语言得以广泛应用的原因之一。
⑦ C语言本身既有一般高级语言的优点,又有低级(汇编)语言的特点。C语言可以允许直接访问内存地址,可以进行位(bit)运算,也可以直接对机器硬件进行操作。因此,既可以用它来编写大型系统软件,也可以用它编写各种应用软件,许多以前只能用汇编语言处理的问题,现在可以改用C语言处理了。
⑧ 语法限制不太严格,程序设计自由度大。C语言由于放宽了语法检查,使程序员有较大的自由度。例如,对数组下标越界不做检查,要由程序设计人员自己保证其正确性。因此,用C语言编写程序,对程序设计人员的要求相应地就要高一些。
上述C语言的特点,在初学时也许还不能深刻理解,待学完C语言之后就会有比较深的体会和感受。
1.4.3 C语言程序的构成
下面通过两个简单的C语言程序,使大家能够对C语言程序有一个最基本的认识。
【例1.4】 求两个整数m与n的和。
程序中,m和n分别表示两个整数,sum表示两个整数的和。
程序代码如下:
#include "stdio.h" main() /* 主函数 */ { int m,n,sum; /* 定义变量m,n,sum */ m=5;n=3; /* 给变量m,n赋值 */ sum=m+n; /* 求m+n的值,并赋给变量sum */ printf("sum is %d\n",sum); /* 输出sum的值 */ }
以上程序由一个称为主函数的main( )函数构成。C语言规定必须用main作为主函数名,其后的一对圆括号“( )”中间可以是空的,但这一对圆括号不能省略。主函数后面是函数体,由一对大括号“{ }”括起来,左大括号“{”表示函数体开始,右大括号“}”表示函数体结束。“/* …… */”表示注释部分,它只是起到帮助阅读程序的作用,对编译和运行不产生任何影响。为方便理解,可采用汉字来注释,注释部分可以出现在程序的任何地方。程序第4行是变量定义语句,定义m、n和sum为整型(int)变量;程序第5行是两条赋值语句,使m和n的值分别为5和3;程序第6行也是一条赋值语句,使sum的值为表达式m+n的值;程序第7行是输出语句,其中,printf( )是C语言的标准输出函数(当引用C语言的标准函数时,需在程序开始处使用文件包含命令将该函数所对应的头文件包含进来。本程序第1行就是文件包含命令,它将标准输入/输出函数的头文件stdio.h包含进来了。关于文件包含的知识将在第 7 章介绍),双引号中的%d 表示在此位置以十进制整数类型输出变量 sum的值,\n 为回车换行符,双引号中其他内容将作为字符串原样输出。因此,该程序的运行结果如下:
sum is 8
【例1.5】 求两个整数中的较小者。
程序中,x、y分别表示两个整数,min表示两个整数之中的较小值。
程序代码如下:
#include "stdio.h" main() /* 主函数 */ { int x,y,min; /* 定义变量 */ int fun(int a,int b); /* 当定义的函数在主函数之后时,要进行函数的声明 */ printf("input x,y:"); /* 提示输入数据 */ scanf("%d,%d",&x,&y); /* 通过键盘输入变量x和y的值 */ min=fun(x,y); /* 调用fun函数,将函数值赋给min */ printf("min=%d\n",min); /* 输出min的值 */ } int fun(int a,int b) /* 定义fun函数,值为整型,a和b为该函数的形式参数 */ { int c; /* 函数中用到的变量c也要定义 */ if(a<b) c=a; else c=b; return(c); /* 将c的值返回至调用处 */ }
该程序包括两个函数:主函数main( )和用户自定义函数fun( )。主函数的第7行是输入语句。scanf( )是C语言的标准输入函数,它的作用是让用户从键盘上输入数据;双引号中的两个%d是格式说明,表示用户输入的数据应该是两个整数;&x和&y中&的含义是取地址,它表示用户从键盘上输入的两个整数将分别送到变量x和y所对应的存储单元中,也就是输入给变量x和y。第8行是调用fun( )函数, 调用时将x和y的值传送给被调函数fun( )中的形参a和b,在被调函数fun( )中,求出两个数中的较小值赋给变量c, 最后由return语句返回c的值到主调函数main( )中的调用处,并将返回的值送给变量min。
该程序的运行情况如下:
input x,y:10,2<Enter> min=2
以上两例中,关于标准输入/输出函数的使用、函数调用、实参和形参的概念,大家可能还不十分清楚,可以先不予以深究,今后在有关章节中还要详细介绍。分析上述程序可以总结出C语言程序的基本构成如下。
(1)C语言程序由函数构成
一个C语言程序至少应包含一个main( )函数(如例1.4),或者包含一个main( )函数和若干个用户自定义函数(如例1.5)。因此,函数是C语言程序的基本单位,相当于其他语言的子程序或过程。
C语言的函数可以分为系统提供的标准函数(库函数,如例1.5中的printf( )和scanf( )函数)和用户自定义函数(如例1.5中的fun( )函数)。各种C语言的编译系统所提供的标准函数的数量和功能以及函数名都不完全相同,标准C提供了100多个标准函数,函数调用使C语言很容易实现程序的模块化。
为了增加程序的可读性,可以用“/*……*/”在任何位置上对 C 语言程序的任何部分作注释,一般在一个程序或函数的开始或某些程序的难点之处加上必要的注释(在VC++6.0环境下也可使用符号“//……”引出注释)。
(2)一个C语言函数通常由两部分组成:函数的首部和函数体
函数的首部包括函数类型、函数名、一对圆括号、函数参数(形参)名和参数类型的说明。比如,例1.5中fun( )函数的首部如图1.9所示。
图1.9 例1.5中fun( )函数的首部
注意:C 语言规定,一个函数名后面必须紧跟一对圆括号,函数的所有形参都必须写在括号内。如果函数没有形参,则括号内可以是空的,但不能省略圆括号,例如,主函数main( )经常不带参数。
函数体就是函数首部后面一对花括号{}内的部分。如果一个函数内有多对花括号,则最外面的一对花括号{}所包含的内容就是该函数的函数体。函数体一般包括说明部分和执行部分。
① 说明部分
说明部分由若干条变量定义语句或函数声明语句组成。C 语言规定,函数中使用的所有变量(或数组)必须在使用前进行定义,否则会在编译时出错。如例1.5中main( )函数的变量定义语句“int x,y,min;”。当然也可以没有说明部分。例如下面的程序代码:
main( ) { printf("It is fine today!");}
该程序的作用是在屏幕上显示以下文字:
It is fine today!
这里没有用到任何变量,所以不需要变量的定义。
② 执行部分
执行部分由若干条执行语句组成。程序的功能就是通过执行部分实现的。C 语言的任何语句都必须以分号“;”结束,分号是C语句的必要组成部分。例如:
y=x+b;
C 语言的语句可以从任意位置开始书写,书写格式自由,一行内可以写多条语句,语句中多个空格与一个空格等效。
一个函数甚至可以既无说明部分,也无执行部分,例如:
comp( ) {}
这个函数是一个空函数,什么作用也没有,但却是合法的。
(3)main( )函数
一个C语言的程序总是从main( )函数开始执行,并终止于main( )函数,而不论main( )函数在整个程序中处于什么样的位置(main( )函数可以放在程序的开头、最后,或某两个函数之间)。但是,为便于理解,通常将main( )函数放在程序的开头或最后。
1.4.4 C语言程序的上机调试过程
如何调试一个C语言程序呢?在不同的环境下调试的方法稍有差异(在VC++6.0环境下C语言程序的调试过程请参见本教材实验篇中的实验一)。但归纳起来一般是依照图1.10所示的过程调试的。
图1.10 程序调试过程
从图1.10可以看出,C语言程序的调试过程基本上可以分为以下4步。
1.编辑
编辑就是用C语言写出源程序。其方法有两种:一种是使用文本编辑程序将源程序输入计算机,经修改认为无误后,以.c 为后缀存入文件系统(C 源程序的后缀一般定为“.c”)中;另一种是使用 C 语言编译系统提供的编辑器将源程序输入计算机,并且存入文件系统中。例如在图1.10中,某用户将自己的源程序文件定名为file.c。
2.编译
调用C语言编译程序对源文件进行编译,即检查其词法、语法、语义方面是否存在错误。
通俗点说,就是检查是否有拼错的关键词,是否有不符合C语言语法规则的表达式及语义方面的矛盾和含混。这些错误在编译阶段都可以查出。
如果有错误,则系统将显示“错误信息”。用户根据指出的错误信息,对源程序进行编辑修改,修改后再重新进行编译,直到编译无误为止。编译后生成的机器指令程序,被称为目标程序,此目标程序名与相应的源程序同名,但其后缀为.obj 。上述源程序文件file.c经编译后得到目标程序file.obj。
3.连接
编译产生的目标文件一般不能直接运行,必须把它所引用的标准函数及源程序指定的目标文件一起装配连接起来,形成完整的可执行文件。一般可执行文件名与源程序文件名同名,后缀为.exe。例如,上述源程序文件file.c经编译连接后得到可执行文件file.exe。
4.执行程序
当程序编译连接后,生成可执行程序便可以运行了,以后用户只需输入可执行目标文件名即可,例如:
file<Enter>