c语言图像水流,程序像河流一样流动—《计算机是怎样跑起来的》

本文介绍了程序的三种基本流程:顺序执行、条件分支和循环,并通过流程图和状态转化图进行可视化表示。强调了结构化程序设计的重要性,避免使用跳转指令以提高程序的可读性和维护性。此外,还提及了中断处理和事件驱动两种特殊程序流程,中断处理类似条件分支,事件驱动则常见于GUI应用中,以用户交互事件来驱动程序执行。
摘要由CSDN通过智能技术生成

本章的主题是程序的流程。程序员一般都是先考虑程序的流程再开始编写程序的。

为什么说程序像河流一样流动

因为作为计算机大脑的CPU在同一时刻基本上只能够解释、执行一条指令。把指令和作为指令操作对象的数据排列起来就形成了程序。从第一条指令往下依次执行,这样看起来程序就像流动起来了。

程序的流程分为三种

与河流的流动方式一样,程序的流程也分为三种。

在程序中,把犹如水流向着一个方向流淌的流程称作“顺序执行”;把犹如水流流着流着产生了支流的流程称作“条件分支”;把犹如水流卷成漩涡的流程称作“循环”。

顺序执行是按照指令记录在内存中的先后顺序依次执行的一种流程。而循环则是在程序的特定范围内反复执行若干次的一种流程。条件分支是根据若干个条件的成立与否,在程序的流程中产生若干个分支的一种流程。

无论规模多么大多么复杂的程序,都是通过把以上三种流程组合起来实现的。

4dab24ae26a2

计算机的硬件系统由CPU、I/O和内存三部分构成。内存中存储着程序,也就是指令和数据。CPU配合着由时钟发生器发出的滴答滴答的时钟信号,从内存中读出指令,然后再依次对其进行解释和执行。

CPU中有各种各样的各司其职的寄存器。其中有一个被称为PC (Program Counter,程序计数器)的寄存器,负责存储内存地址,该地址指向下一条即将执行的指令。每解释执行完一条指令,PC寄存器的值就会自动被更新为下一条指令的地址。

PC寄存器的值在大多数情况下只会增加。下面假设PC寄存器正指向内存中一个从10号地址开始的3字节指令。CPU解释执行完这条指令后,PC寄存器中的值就变成10+3 = 13了。也就是说,程序基本上是从内存中的低地址(编号较小的地址)开始,向着高地址(编号较大的地址)流下去的。我们把程序的这种流动称为“顺序执行”。如上图所示。

用流程图表示程序的流程

流程图,正如其名,就是表示程序流程(Flow)的图(Chart)。

很多专业的程序员,他们在编写程序前,都会通过画流程图或是类似的图来思考程序的流程,如下图。

4dab24ae26a2

流程图的方便之处在于它并不依赖于特定的编程语言。

编程语言只不过是将流程图上的流程用程序重现出来罢了。

顺序执行只需用直线将矩形框连接起来(a)。条件分支用菱形表示(b)。循环的表示方法是通过条件分支回到前面的处理步骤(c)。这样就能将所有的流程都表示出来了。

实际上用于表示程序流程的最基础的符号并没有多少。只要记住以下表的符号就够用了。

4dab24ae26a2

用流程图表示三种流程

4dab24ae26a2

循环的另一种流程图表示法

4dab24ae26a2

对于帽子形状和短裤形状的符号,为了表示它们是成对出现的,要在上面写下适当的名字。然后用“帽子”和“短裤”把需要反复执行的步骤包围起来。如果要在循环中嵌套循环,就需要对每个循环分别使用一对“帽子”和“短裤”。为了区分成对出现的“帽子”和“短裤”,要为每一对起不同的名字。

为什么用这种方式表示循环流程

在计算机硬件上的操作中,循环是通过当满足条件时就返回到之前处理过的步骤来实现的。一旦使用了机器语言或汇编语言所提供的跳转指令,就可以将PC寄存器的值设置为任意的内存地址。如果将它的值设为之前执行过的步骤所对应的内存地址,那么就构成了循环。因此,在表示循环的时候,仅仅使用带有菱形符号的流程图也就足够了。用机器语言或者汇编语言表示循环时,都是先进行某种比较,再根据比较结果,跳转到之前的地址,如下图。

4dab24ae26a2

现在还在使用机器语言或汇编语言的人已经不多了。程序员使用的都是能够更加高效地编写程序的高级语言,如BASIC、C语言和Java等。在这些高级语言中,程序员使用“程序块”表示循环而不是跳转指令。

所谓“程序块”就是程序中代码的集合。程序中要被循环处理的部分,就是一种程序块。

而很多高级语言中,都会用一对关键字来表示需要循环的程序块。例如在VBScript中,是用For和Next两个关键字表示循环的程序块的,如下图。这两个关键字就跟“帽子”和“裤子”相对应,所以用帽子和短裤符号表示循环的方法就适用于使用了程序块的高级语言。

For i = 1 To 5 相当于“帽子”

' 处理步骤

Next 相当于“短裤”

4dab24ae26a2

在高级语言中,条件分支也是由程序块表示的。在VBScript中,使用If、ElseIf、Else、End If表示条件分支的程序块。

但是在直接表示硬件操作的机器语言和汇编语言中,是通过条件分支返回到之前处理过的指令来实现循环的,并没有相当于For或者Next的指令。条件分支本身也是通过跳转指令实现的。根据比较操作的结果,跳转到之前处理过的步骤就是循环;跳转到之后尚未处理的步骤就是条件分支,如下图。

4dab24ae26a2

高级语言表示的条件分支

4dab24ae26a2

结构化程序设计

结构化程序设计是由学者戴克斯特拉提倡的一种编程风格。简单地说,所谓结构化程序设计就是“为了把程序编写得具备结构性,仅使用顺序执行、条件分支和循环表示程序的流程即可,而不再使用跳转指令”。

作为计算机硬件上的行为,无论是条件分支还是循环都必须使用跳转指令实现。但是在VBScript等高级语言中,可以用If~ElseIf~Else~End If程序块表示条件分支,用For~Next程序块表示循环。跳转指令因此就变得可有可无了。

但是即便如此,在很多高级语言中,还是提供了与机器语言中跳转指令相当的语句,例如VBScript中的GoTo语句。其实戴克斯特拉想表达的是“既然好不容易使用上了高级语言,就别再使用相当于跳转指令的语句了。即使不使用跳转语句,程序的所有流程仍然可以表述出来”。

因为跳转指令所带来的危害性不小,会使程序陷入到流程错综复杂的状态,就像意大利面条那样缠绕在一起,如下图。

4dab24ae26a2

在程序设计的世界中,如果看到了以“结构化”开头的术语,就可以这样认为:程序的流程是由程序块表示的,而不是用GoTo语句等跳转指令实现的。

但是即使使用了结构化异常处理,在硬件上使用的也还是跳转指令,只是说在高级语言中不用再写相当于跳转指令的语句了。如果把用高级语言所编写的程序转换成机器语言,像程序块这样的语句还是会被转换为跳转指令。

画流程图来思考算法

所谓算法(Algorithm),就是解决既定问题的步骤。想让计算机解决问题,就需要把问题的解法步骤转换成程序的流程。所以表示程序流程的流程图本身就能解释算法。

思考算法时的要点是要分两步走,先从整体上考虑程序的粗略流程,再考虑程序各个部分细节的流程。

粗略的流程,这是一种相当简单的流程,虽然或多或少会有例外,但是几乎所有的程序从整体来看都具有一个一成不变的流程,那就是“初始化处理”→“循环处理”→“收尾处理”。

4dab24ae26a2

特殊的程序流程——中断处理

中断处理是指计算机使程序的流程突然跳转到程序中的特定地方,这样的地方被称为中断处理例程(Routine)或是中断处理程序(Handler),而这种跳转是通过CPU所具备的硬件功能实现的。人们通常把中断处理比作是接听电话。假设诸位都正坐在书桌前处理文件,这时突然来电话了,诸位就不得不停下手头的工作去接电话,接完电话再回到之前的工作。像这样由于外部的原因使正常的流程中断,中断后再返回到之前流程的过程就是中断处理流程。

在Z80 CPU中有INT和NMI两个引脚,它们可以接收从I/O设备发出的中断请求信号。以硬件形式连接到CPU上的I/O模块会发出中断请求信号,CPU根据该信号执行相应的中断处理程序。在诸位使用的个人计算机上,中断请求信号是由连接到周边设备上的I/O模块发出的。

4dab24ae26a2

中断处理以从硬件发出的请求为条件,使程序的流程产生分支,因此可以说它是一种特殊的条件分支。可是,在诸位编写的程序中并不需要编写有关中断处理的代码。因为处理中断请求的程序,或是内置于被烧录在计算机ROM中的BIOS系统(Basic Input Output System,基本输入输出系统)中,或是内置于Windows等操作系统中。诸位只需要先记住以下两点即可:计算机具有硬件上处理中断的能力;中断一词的英文是Interrupt。

特殊的程序流程——事件驱动

经常用事件驱动的方式编写那些工作在GUI(Graphical User Inteface,图形用户界面)环境中的应用程序,例如Windows操作系统中的应用程序。

听起来好像挺复杂的,但其实如果把事件驱动想象成是两个程序在对话,理解起来就简单了。

下图列出了一段用C语言编写的Windows应用程序,这里只列出了程序的骨架。在程序中有WinMain()和WndProc()两个函数(代码块)。WinMain()是在程序启动时被调用的主例程(Main Routine)。而WndProc()并不会被诸位所编写的程序本身调用,Windows操作系统才是WndProc()的调用者。这种机制就使得Windows和诸位所编写的应用程序这两个程序之间可以进行对话。

4dab24ae26a2

通常把用户在应用程序中点击鼠标或者敲击键盘这样的操作称作“事件”(Event)。负责检测事件的是Windows。Windows通过调用应用程序的WndProc()函数通知应用程序事件的发生。而应用程序则根据事件的类型做出相应的处理。这种机制就是事件驱动。可以说事件驱动也是一种特殊的条件分支,它以从Windows送来的通知为条件,根据通知的内容决定程序下一步的流程。

事件驱动是一种适用于GUI环境的编程风格,在这种环境中用户可以通过鼠标和键盘来操作应用程序。虽然事件驱动的流程也可以用流程图表示,但是由于要排列很多的菱形符号(表示条件分支),画起来会很复杂。所以下面介绍便于表示事件驱动的“状态转化图”,如下图。

4dab24ae26a2

也可以用“状态转化表”表示,如下图。

4dab24ae26a2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值