第1章C语言概述
1.1C语言发展简史
在计算机科学应用领域,人与计算机之间交流最通用的手段是程序设计语言。当人们想利用计算机解决某个问题时,必须用程序设计语言安排好处理步骤,并存入计算机内供计算机执行,这些用程序设计语言安排好的处理步骤称为计算机程序。程序是计算机操作指令的集合。用程序设计语言编制计算机程序的过程叫做程序设计。
目前有很多程序设计语言,而且新的语言不断涌现。常见的有Fortran、BASIC、COBOL、Pascal、C、C++、Java、Delphi等。各类语言都有其各自的特点和适用的领域。
C语言是一种通用的程序设计语言,由于它很适合用来编写编译器和操作系统,并进行嵌入式系统开发,因此被称为“系统编程语言”,但它同样适用于编写不同领域中的应用程序。
1.C语言的产生
C语言是一种被广泛应用的计算机高级程序设计语言,是在B语言的基础上发展起来的,它经历了不同的发展阶段。
早期的系统软件设计均采用汇编语言,例如,大家熟知的UNIX操作系统。尽管汇编语言在可移植性、可维护性和描述问题的效率等方面远远不及高级程序设计语言,但是一般的高级语言有时难以实现汇编语言的某些功能。
那么,能否设计出一种集汇编语言与高级语言的优点于一身的语言呢?这种思路促成了UNIX系统的开发者(美国贝尔实验室的Ken Thompson)于1970年设计出了既简单又便于硬件操作的B语言,并用B语言写了第一个UNIX操作系统,这个操作系统先在PDP-7上实现,1971年又在PDP-11/20上实现。
B语言的前身是BCPL(Basic Combined Programming Language),它是英国剑桥大学的Matin Richards在1967年基于CPL语言设计的,而CPL语言又是在1963年基于ALGOL 60产生的。
1972~1973年,贝尔实验室的D.M.Ritchie在B语言的基础上设计出C语言,该语言弥补了B语言过于简单、功能有限的不足。
1973年,KenThompson和D.M.Ritchie合作将90%以上的UNIX代码用C改写。随着改写UNIX操作系统的成功,C语言也逐渐被人们接受。
1987年以后,C语言已先后被移植到大、中、小、微型机上,并独立于UNIX和PDP,从而得到了广泛应用。
2.C语言的发展和应用
1978年,B.M.Kernighan和D.M.Ritchie合写了一本经典著作—《C程序设计语言》(The C Programming Language,中文版、影印版均已由机械工业出版社引进出版),它奠定了C语言的基础,被称为标准C。
1983年,美国国家标准学会(ANSI)根据C语言问世以来的各种版本对C的发展和扩充,制订了新的标准,称为ANSI
C。1987年又公布了新标准,称为87 ANSI C。目前流行的多种版本的C语言编译系统都是以此为基础的。
在ANSI标准化后,C语言的标准在相当一段时间内都保持不变,直到20世纪90年代才进行了改进,形成ISO9899:1999(1999年出版),这个版本就是通常提及的C99。它于2000年3月被ANSI采用。
3.C语言和C++语言交融发展
由于C语言是面向过程的结构化和模块化的程序设计语言,当处理的问题比较复杂、规模庞大时,就显现出一些不足,由此面向对象的程序设计语言C++应运而生。C++的基础是C,它保留了C的所有优点,增加了面向对象机制,并且与之完全兼容。绝大多数C语言程序可以不经修改直接在C++环境中运行。
. 1.2C语言的特点
C语言产生的历史并不长,它之所以后来居上,成为深受欢迎的高级语言之一,是因为和其他早期的高级语言相比,它具有以下优点:
1)兼具高级、低级语言的双重能力。C语言允许直接访问物理地址,能进行位操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作,所以又被称为中级语言。
2)生成的目标代码质量好,程序执行效率高。C语言具有汇编语言的许多特性,一般只比汇编程序生成的目标代码效率低10%~20%,可以开发出执行速度很快的程序。
3)语言简洁,结构清晰。C程序通常是由若干函数组成的,强大的函数功能为程序的模块化和结构化提供了保证,因此程序简洁清晰,可读性强。
4)语言表达能力强。C语言运算符丰富,例如,在C语言中,把括号、赋值、强制类型转换等都作为运算符处理。C语言具有现代化语言的各种数据结构,如整型、字符型、数组型、指针型、结构体和共用体等,而且具有结构化的控制语句。
5)程序通用性、可移植性好。C语言没有依赖于硬件的输入/输出语句,而采用系统的库函数进行输入/输出操作,因此C语言不依赖于任何硬件系统,这种特性使得用C语言编写的程序很容易移植到其他环境中。
当然,C语言也有自身的不足,和其他高级语言相比,其语法限制不太严格,例如,对变量的类型约束不严格,影响程序的安全性,对数组下标越界不作检查等。从应用的角度来看,C语言比其他高级语言较难掌握。
总之,C语言既具有高级语言的特点,又具有汇编语言的特点;既是一个成功的系统设计语言,又是一个实用的程序设计语言;既能用来编写不依赖计算机硬件的应用程序,又能用来编写各种系统程序。它是一种深受欢迎、应用广泛的程序设计语言。
1.3简单C语言程序举例
在这一节中,我们通过两个简单的C语言程序例子来介绍C语言的程序结构,并对C语言的基本语法成分进行相应的说明,以便使读者对C语言程序有一个大致了解。
【例1-1】
计算矩形的面积。
#include <stdio.h> /*1:编译预处理*/
int main() /*2:主函数*/
{ /*3:函数体开始*/
float h,w,area; /*4:声明部分,
定义变量*/
h=10.5; /*5:以下4条C语句为执行部分,给变量h和w赋值*/
w=20.5;
area=h*w; /*7:计算矩形的面积*/
printf("area=%6.2f\n",
area); /*8:输出area的值*/
return
0; /*9:返回值为0*/
} /*10:函数体结束*/
运行结果:
area=215.25
每行中的/*……*/内包括表示程序注释的内容。
第1行:是一个编译预处理,在程序编译前执行,指示编译程序如何对源程序进行处理。它以“#”开头,结尾不加分号,以示和C语句的区别。
第2行:main表示主函数,每一个C程序都必须有一个主函数,int表示主函数为整型。函数体由第3行和第9行的一对花括号括起来。
第4行:是变量声明部分,定义变量h、w和area为实型变量。
第5、6行:是两条赋值语句,给变量h赋值10.5,w赋值20.5。
第7行:将算术表达式h*w的值赋予变量area。
第8行:调用函数printf输出矩形面积值。
第9行:向操作系统返回一个零值,如果程序不能正常执行,则会自动向操作系统返回一个非零值,一般为-1。
【例1-2】
计算两个矩形的面积之和。
#include <stdio.h> /*1:编译预处理*/
double
area(double h,
double w
) /*2:定义函数area*/
{double s;
s=h*w;
return s; /*6:返回s的值,
return是关键字*/
}
int main() //8:主函数
{
double h1,h2,w1,w2,s1,s2; //10:声明部分,
定义变量
h1=10.5;
w1=20.5;
h2=1.5*h1;
w2=1.5*w1; //12:计算变量h2,
w2的值
s1=area(h1,
w1); //13:调用area函数,
将得到的返回值赋给变量s1
s2=area(h2,w2);
printf("area=%6.2f\n",s1+s2); //15:输出两个矩形的面积之和
return 0;
}
运行结果:
area=699.56
本程序包括主函数main、函数area(被主函数调用)和一个编译预处理指令。
第2行:从该行开始到第6行定义函数area,包括函数类型、函数名和函数体等部分。
第13、14行:调用函数area,将两次调用的返回值分别赋给变量s1和s2。
第15行:计算并输出两个矩形的面积之和。其中每行中“//”后面的所有字符也是注释的内容。
上述两个函数构成了一个完整的程序,称为源程序。它以文件的方式存在,文件中包含函数的源程序代码。可以把这两个函数放在一个文件中,当程序语句多的时候也可以分别以函数为单位放在两个以上的文件中,C语言规定保存C源程序文件的扩展名为“.c”。
1.4C语言程序的组成与结构
通过以上两个例子,我们对C语言程序的组成和结构有了初步和直观的了解,总结如下:
1)一个C语言程序的主体结构是由一个或若干个函数构成的。这些函数的代码以一个或若干个文件的形式保存。这些函数中必须有且只能有一个名为main的主函数。
2)主函数main是程序的入口,它可以出现在程序的任何位置。一个C程序总是从主函数main开始执行,最后结束于主函数。
3)C程序中的函数包括:主函数main,用户自定义函数(例如,例1-2中的area),系统提供的库函数(例如,输出函数
printf)。
4)函数由函数头和函数体两部分组成,函数头由函数类型的定义、函数名和参数表组成,函数体由声明部分(所使用变量和函数的说明)和若干执行语句组成。
5)语句由关键字和表达式组成,每个语句和声明部分的结尾都必须加分号。复合语句的开头和结尾使用左、右花括号{
}。
关键字是C语言系统为了清晰地表达程序的功能而使用的一些英文单词或单词缩写。例如,例1-2中的
return就是关键字。
用运算符将操作对象连接起来、符合C语言语法的式子称为表达式。表达式的组成元素有:变量、常量、函数调用、运算符。这些组成元素是以标识符和关键字的形式存在的。例如,例1-2中的h2=1.5*h1和
w1=20.5
都是表达式。
6)程序中“/**/”内的文字是程序的注释部分,是便于阅读理解程序的解释性附加文本,程序编译器完全忽略注释部分的内容。此外,在程序调试时,也可以将一部分代码转换为注释保留,而不必删除,以提高程序调试的效率。
另外,一些C语言开发工具还支持用“//”标识注释部分,如果某行程序代码前面插入符号“//”,该符号后面的部分就变为注释行,并且本行有效,不能跨行。一般情况下,如果注释内容在程序中占用多行,习惯用“/*
*/”,而单行注释内容用“//”
标识即可。
从以上的分析可以发现,C程序的组织和构造与我们日常的文章的结构很类似,如表1-1所示。
表1-1文章和C语言对应的层次结构
文章的层次结构 对应C程序的层次结构 文章的层次结构 对应C程序的层次结构
文章 程序 句子 语句
章节 文件 词组 表达式
段落 函数 字 常量、变量、关键字、运算符等
开头第一段 主函数
在一般语言的学习过程中,我们是先学字、词组,然后造句,阅读范文,最后写作文。现在学习计算机语言,我们也同样遵循这个规律,即先学习常量、变量的类型和定义方法,然后依次学习表达式、语句和函数等,同时阅读一些程序范例,最后编写程序。当然二者也有本质上的区别,一般语言的学习以形象思维为主,而计算机语言的学习是以逻辑思维为主。C语言的程序结构如图1-1所示。
图1-1C语言程序的层次结构图
1.5C语言程序的开发步骤
一个C语言程序从最初编写到得到最终结果,大致经过以下几个步骤:
1)编辑源程序。选择一种C语言开发工具,输入编写好的程序代码,称为源程序,它以文件的方式存在,文件的扩展名为“.c”。
2)编译源程序。为了使计算机能执行高级语言源程序,必须把源程序转换为二进制形式的目标程序,这个过程称为编译源程序。
编译是以源程序文件为单位分别进行的,每一个源程序文件对应生成一个目标文件,目标文件的扩展名为“.obj”。
编译过程中对源程序的全部内容进行检查,例如检查程序中关键字的拼写是否正确,根据程序的上下文检查语法是否有错等,编译结束后系统显示所有的编译出错信息。
一般编译系统的出错信息有两种:一种是错误(error)信息,这类错误出现后,系统不生成目标文件,必须改正后重新编译;另一种是警告(warning)信息,是指一些不影响程序运行的不合理现象或轻微错误。例如,程序中定义了一个变量,却一直没有使用,这类警告信息出现后,系统可以生成目标文件。
3)连接目标文件。编译结束,得到一个或多个目标文件,此时要用系统提供的“连接程序”(linker)将一个程序的所有目标文件和系统的库文件以及系统提供的其他信息连接起来,最终形成一个可执行的二进制文件,可执行文件的扩展名为“.exe”。
4)运行程序。运行最终形成的可执行文件,得到运行的结果。
5)结果分析。分析程序的运行结果,如果发现结果不对,应检查程序或算法是否有问题,修改程序后再重复上面的步骤。其过程如图1-2所示。
图1-2
C语言程序的开发步骤
小结
本章首先叙述了程序设计的基本概念和C语言产生和发展的历史过程,然后与其他高级语言进行对比,列举了C语言的特点,再通过两个简单的C程序的实例,描述了C语言程序的基本组成和结构特点,最后介绍了C语言程序开发各个步骤的内容。
通过本章的学习,读者应该对程序设计的概念有初步的认识,对C语言总体结构和开发步骤有初步的了解。建议学习本章内容后,尽快在计算机上编译、运行一个简单的C语言程序。在今后的学习中,读者会发现有些问题文字叙述很难领会,但上机编程后,其实问题很容易理解,即所谓“在编程中学习编程”。
习题
一、简答题
简要回答下列问题。
1.程序的定义是什么?程序主要由几部分组成?
2.C语言的主要特点有哪些?
3.C语言程序是由哪些部分组成的,各部分的作用是什么?
二、选择题
以下各题在给定的四个答案中选择一个正确答案。
1.以下叙述正确的是()。
A.C语言允许直接访问物理地址,可以直接对硬件进行操作
B.C语言程序不用编译,即可被计算机识别运行
C.C语言不允许直接访问物理地址,不可以直接对硬件进行操作
D.C语言程序只需编译,不需连接即可被计算机运行
2.在一个C程序中(
)。
A.main函数出现在所有函数之前,C程序不一定都有main函数
B.main函数可以在任何地方出现,一个C程序必须有且仅有一个main函数
C.main函数必须出现在所有函数之后,一个C程序只能有一个main函数
D.main函数出现在固定位置,一个C程序可以有多个main函数
三、填空题
1.C语言开发工具直接输入的程序代码是A文件,经过编译后生成的是B文件,经过连接后生成的是C文件。
2.C语言源文件的后缀是A,经过编译后生成的文件的后缀是B,经过连接后生成的文件的后缀是C。
四、编写程序题
输入下面的程序,上机调试并运行。
int main()
{float r,s;
r=15.5;
s=2*3.14*r;
printf("r=%4.2f,s=%\n",r,s);
return 0;
}