1.1 什么是编程

1.1.1 计算机如何工作

编程(Programming)就是编写计算机程序。那么,究竟什么是程序(Program)呢?

要理解“程序”这个概念,必须首先了解计算机工作的基本原理。

1.计算机的组成

通常我们所看到的计算机,一般都会有键盘、鼠标、显示器、机箱等几个部分。其中,键盘和鼠标在功能上属于计算机的输入设备(Input Device)。而显示器或打印机都属于输出设备(Output Device),如图1-1所示。

1.1 什么是编程 - 图1

图1-1 计算机外观

从宏观考察整个计算机的运行情况,则计算机无外乎是从输入设备接受数据(及命令),在内部处理之后,再把结果输出到输出设备上的一种电子设备而已。当然,输入设备不一定非得是键盘和鼠标,输出设备也不一定非得是显示器。

而计算机本身的主要工作是在机箱内部完成的。在机箱内部一般有一块很大的电子线路板叫做主板(Main Board),主板通过上面的所谓的总线(Bus)连接着计算机所有的设备,计算机的主要工作都是在这里完成的。在主板上,有几个主要的关键部件,如ROM、RAM、CPU等。

2.CPU

CPU是中央处理器(Central Processing Unit)的简称,它的功能包括两个:进行运算和指挥计算机其他各部件进行工作。CPU进行运算工作的那部分叫做运算器(Arithmetical Unit,AU),指挥计算机其他部分工作的部分被称之为控制器(Control Unit,CU)。

CPU的运算工作是由CPU内部一个叫做运算器的部分完成的。这里的运算只是针对有限位数二进制数值的四则运算,或者判断某个二进制数是否为0这样简单的逻辑运算。

我们要求计算机执行的所有任务都是被分解成这样极小的计算和极其简单的“小动作”的有序组合来完成的。尽管这种“小动作”极其微小而琐碎,但由于计算机完成得很快,所以平时我们根本感觉不到这一点。

3.内存

尽管是两个物理器件,但由于功能相同,ROM和RAM都被归类为存储器(Memery Unit,MU)。由于计算机的工作还需要另外一些辅助的存储设备,所以RAM、ROM被合称为主存或内存。我们要求计算机执行的任务被分解成一个个的“小动作”,在任务被执行时,就被存储在这里。

内存目前由半导体材料构成,其基本元件有两种状态,分别表示0和1。大量的这种基本元件的状态组成了一幅类似于下面的图像:

0000001100101001011100101010101010101010101011010101011010101011……

内存中每个元件的状态(0或1)被叫做一个bit或位(和我们平时使用的十进制的“位”的概念相似,只是这里每一个位只能写0或1,而十进制的每一个位可以写0~9十个数字)。每若干个相邻的元件被划分为一组(通常是8个bit一组)——每个这样的元件组被称为一个Byte或字节,如图1-2所示。就如同下面这样:

1.1 什么是编程 - 图2

图1-2 位与字节

00000011 00101001 01110010 10101010 10101010 10101101 01010110 10101011……

每若干连续的字节可能表示让计算机执行的一个动作,也可能表示一个需要被计算的数据,控制器每次读取若干字节,然后通过总线将其变成电信号,让计算机执行各种对应的操作或计算,之后再读取后面的若干字节数据,以执行整个任务。每个让计算机完成一个动作的一组二进制数都是一条指令(Instruction)。

由此可见,所谓指令就是能被计算机识别并执行的二进制代码,它确定了计算机的某一个具体操作。计算机的运行是在控制器的指挥、协调下完成的。然而控制器本身并不了解究竟应该让计算机各个部分执行哪些动作。控制器是根据存储器(这里指的是内存,也叫主存)中的内容来指挥各个部件做动作的。

为解决某个具体问题或完成一项特定任务的许多指令的有序的集合就叫程序。这种把计算机要执行的动作写成一系列二进制数形式的指令,并在执行前将它存储在内存中,然后再由控制器自动读取执行的思想就是所谓“存储程序控制原理”。

1.1.2 内存中的程序是哪里来的

现在我们已经知道计算机是如何运行的了,然而这和我们在键盘(或鼠标)上发出一个宏观的运行命令之间还有不小的距离。程序究竟是如何存储到内存以及程序究竟是如何编写的呢?

第一个问题的答案是,大多数程序平时都是以文件的方式存储在外部存储设备中的,这些文件的扩展名通常是“.EXE”,叫做可执行文件。

这些可执行文件在需要执行的时候,可以通过双击代表其文件的图标,如图1-3所示,或在命令行写上其名字然后按回车键,之后该文件的内容就会被复制到内存,然后由控制器逐条读取并执行。

1.1 什么是编程 - 图3

图1-3 可执行文件的装载

另一个问题是,这些文件是怎么生成的?如何才能把我们的要求变成一条条诸如01101110……那样的指令,并“制造”出由这样的指令构成的可执行文件?下面小节的内容将回答这个问题。

1.1.3 可执行文件的制作

1.机器语言

直接用二进制代码表示计算机命令的编程语言叫做机器语言(Machine Language),这是计算机唯一能够识别的语言。一般来说,不同型号的计算机能识别的机器语言是互不相同的。由于机器语言是CPU直接使用的语言,与人类的语言相距甚远,因此被称为“低级语言”。

毫无疑问的是,写出如下的程序:

1.1 什么是编程 - 图4

对绝大多数人来说是一种巨大的痛苦和折磨。要知道,通常即使是一个很小的程序,至少也需要几千条指令,而且这种形式的指令非常难于理解、阅读、记忆、编写、检查和修改。

2.汇编语言

为了编写程序的方便,提高计算机的使用效率,后来出现了汇编语言(Assembly Language)。汇编语言是用一些约定的文字、符号和数字,按规定格式表示各种不同的指令,然后再用这些来编写程序的语言。例如:

1.1 什么是编程 - 图5

显而易见的是,汇编语言程序要比机器语言程序更容易被理解和修改。汇编语言程序的每一条语句都对应一条相应的机器指令。汇编语言用助记符(add、move……)代替了操作码(10101110 10111101……),用地址符代替了操作数,同时常量也被写成了十六进制。由于这种替代,机器语言被“符号化”了,所以汇编语言又被称为符号语言(Symbolic Language)。

汇编语言并不是CPU能够直接识别并执行的语言,因此汇编语言编写的程序需要一种专门的软件(术语叫汇编器,Assembler)把汇编语言程序“翻译”成对应的机器语言,而这个过程就叫作“汇编”。

尽管汇编语言编程比机器语言编程要更容易,但对于多数人来说,在能够使用汇编语言进行编程之前,仍需要花费大量时间去学习、熟悉CPU指令集,使用汇编语言编程依然是件很不容易的事情。而且汇编语言同机器语言一样也是低级语言,对于不同型号的计算机(CPU)来说也不具有通用性。

3.高级语言

使用低级语言编程极大地限制了计算机被广泛应用的可能性。人类后来发明了更加易用的所谓高级语言(High-level Language)。这种语言有些类似于简单的自然语言或数学语言,普通人经过强度不大的学习之后都可以进行编程,从此编程不再是程序员们的专利了。高级语言使得人们可以把主要精力放在问题本身以及解决的方案上,而不是像低级语言那样要求人们在考虑问题本身的同时,还必须考虑计算机硬件方面烦琐的细节。高级语言的另外一个优点是通常与CPU型号无关,高级语言编写的程序可以在不同的计算机上运行(通常把这叫做具有可移植性,Portability)。

用高级语言编写出的可供人阅读的程序叫做源程序(Source Program),也叫源代码(Source Code),一般以文件的形式存储在磁盘上,所以也叫源文件(Source File)。

和汇编语言编写的程序一样,高级语言编写的源程序也不能直接被CPU识别并执行。也需要一种专门的软件(术语叫编译器,Compiler)“翻译”成机器语言,这个过程叫做“编译”。编译后的结果一般存储成一个二进制指令集合的文件,扩展名是.EXE,叫做可执行文件,如图1-4所示。可执行文件也不是严格意义上的计算机执行时的程序,还需要使用者通过操作系统装入内存并运行,这就是计算机真正执行的程序。

1.1 什么是编程 - 图6

图1-4 可执行文件的生成

4.C语言

高级语言有许多种,C语言是其中之一。C语言是D.M.Ritchie于1972年至1973年间设计出来的。1978年,Brian W.Kernighian和Dennis M.Ritchie(合称K&R)出版了在计算机史上影响深远的名著《The C Programming Language》,从而使C语言成为了世界上最流行、应用最为广泛的高级程序设计语言。

30多年过去了,许多曾经风行一时的高级语言早已风光不在,影响力逐步下降甚至是逐步消失,但C语言的魅力依旧如昨。除了承认C语言是一种最优秀和最杰出的程序设计语言之外,没有其他的办法可以理解、解释这种奇迹。

1.1.4 C语言的演化

C语言,这种人为定义出来的语言,在问世之初并没有任何官方标准。1978年K&R合著的《The C Programming Language》所描述的C语言是当时实际应用中的标准,也是稍后广泛使用的C语言各种版本的基础,它被称为C78或传统C。

随着C语言的影响日益加大,它迅速地成为最受欢迎的语言之一。使用C的人越来越多,C语言出现了各种“方言”——各种编译器所翻译的的C语言之间或多或少有一些差异。C语言于是进入了的自己的“春秋战国”时代。

1983年,美国国家标准化协会(American National Standards Institute,ANSI)根据C语言问世以来的各种版本对C语言进行了发展和扩充,经过了长时间的工作之后提出了C语言的标准定义,这个C标准被称为ANSI C。ANSI C比传统C有了很大的发展,但仍是以传统C作为基础的。作为回报,K&R修改了他们的经典著作《The C Programming Language》,按照ANSI C的标准重写了该书,以表示对ANSI C的认同。

ANSI C本身也是在不断改变中的,1987年87 ANSI C公布。1989年又公布了目前多数编译系统所遵循的C89,这个标准在1990年被国际标准化组织(International Standards Organization,ISO)采纳为国际标准(ISO/IEC 9899: 1990-Programming languages—C),所以也有时被称为C 90。这个版本的C标准是目前事实上的现行C语言标准。我国目前的国家标准(GB/T 15272-94程序设计语言C)也是据此订立。

C 90订立时的一个原则就是“保持C的精神”,这种精神可以用下面几句话概括。

■ “信任程序员”(Trust the programmer)。

■ “不妨碍程序员行需为之事”(Don't prevent the programmer from doing what needs to be done)。

■ “保持语言的简洁精练”(Keep the language small and simple)。

■ “为操作提供唯一的方式”(Provide only one way to do an operation)。

■ “速度优于可移植性”(Make it fast,even if it is not guaranteed to be portable)。

最新的C语言标准(ISO 9899:1999)是在1999年由ISO颁布并在2000年3月被ANSI采纳的C99。新标准的目标是支持国际化编程,改进那些明显的缺点,并增强数值计算能力。C99目前尚未得到所有编译器的一致支持。不过,本书所介绍的编译器支持大多数C99的新特性。