
1.2 C程序的基本结构和运行过程
任何一种语言的程序都有其特定的组成结构。这种结构既表示了程序的基本组成元素,又体现了程序设计的理念。例如,C程序是由若干个函数组成的,每个函数均可用于描述一项操作的具体实现过程。因此,C程序的设计目标是以操作为核心的,整个程序就是一系列操作的具体描述。本节将借助几个简单的例子,说明C程序的基本结构和运行一个C程序的基本过程。
1.2.1 几个简单的C程序
在学习C语言的其他内容之前,了解并掌握程序的基本结构,对尽快学会编写简单的C程序,理解C程序中各个组成要素的作用是十分必要的。下面将本着由浅入深、循序渐进的原则,用几个简单的程序实例,来介绍C程序的基本组成结构。
【例1-1】 文本行的输出。
请编写一个程序,输出文本行“This is a C program.”。
〖程序代码〗
#include <stdio.h>
main( )
{
printf("\nThis is a C program.\n"); /*显示文本行This is a C program.*/
}
这是一个简单的 C 程序,它的基本功能是在屏幕上显示一个文本行“This is a C program.”。
下面解释这个程序中每行内容的主要含义。
第 1 行是一条编译预处理命令,其含义是将头文件“stdio.h”嵌入到本程序中。这个头文件是C语言编译系统提供的,其中放置着许多与输入/输出操作有关的标准函数声明。由于这个程序需要使用标准输出函数 printf,所以必须将头文件嵌入到程序中,使其符合任何函数都必须先声明后使用的规则。
第2~5行定义了一个名为main的函数。main( )是函数的首部,{…}括起来的部分是函数体,其中包含了组成该函数的若干条语句。本例中,函数体内只有一条调用标准输出函数printf 的语句,用于数据的显示输出。其中,双引号内的字符序列是程序运行后将在屏幕上显示的文本行内容,“\n”是换行符,表示将光标移到下一行,再显示后面的内容。
这里需要说明一点,在C程序中,名为main的函数的特殊性主要有以下两点:
(1)任何一个完整的C程序都必须有且仅有一个名为main的主函数;
(2)当程序运行后,系统将率先自动地调用主函数,这是每个C程序执行的起始点。
由此可见,这个程序展示了一个最简单的C程序结构,即任何C程序都必须包含一个名为main的主函数,而该程序的执行过程就是依次执行函数体内的各条语句。
【例1-2】 整数求和。
请编写一个程序,计算1~100的整数和。
〖程序代码〗
#include <stdio.h>
main( )
{
int i, sum; /* 定义变量 */
sum = 0; /* 为变量sum赋初值0 */
for (i=1; i<=100; i++) { /* 计算1~100的整数和 */
sum = sum + i;
}
printf("\n1+2+3+…+99+100=%d\n", sum); /* 输出计算结果 */
}
这个程序的基本功能是:计算并输出1~100的整数和。
运行这个程序后,可以在屏幕上看到的结果是:1+2+3+…+99+100=5 050。
与【例 1-1】相同,这个程序仅由一个主函数构成。在函数体的第 1 行中定义了两个名为i和sum的整型变量,也就是可以保存整数的存储单元。C语言规定:所有的变量都必须先定义后使用。紧随其后的for语句序列描述了在变量sum中依次累加1~100的过程。最后用printf输出的累加和。语句右侧 /*…*/ 之间的内容是程序的注释,其中包含了一些对程序内容的说明性文字,它们对程序的执行没有任何作用,只是为了提高程序的可读性。
【例1-3】 两个整数中的最大值。
通过键盘输入两个整数,输出其中较大的整数。
〖程序代码〗
#include <stdio.h>
int maxValue(int x, int y) /* 返回x、y中较大值 */
{
int max;
if (x > y) /* 如果x>y,将x赋给max */
max = x;
else /* 否则将y赋给max */
max = y;
return max; /* 返回max */
}
main( )
{
int x, y, z; /* 定义变量 */
printf("Enter 2 integers:"); /* 显示提示信息 */
scanf("%d%d", &x, &y); /* 输入两个整数 */
z = maxValue(x, y);
printf("The larger value is %d.\n", z); /* 显示x、y中较大者 */
}
这个程序的基本功能是:用户通过键盘输入两个整数,然后输出其中较大的整数。例如,运行这个程序后,首先会在屏幕上显示下列文本行:
Enter 2 integers:
当用户看到这个提示信息后,立即通过键盘输入下列内容:
48 89
然后,按“Enter”键,就可以在屏幕上看到下面方框中显示的结果:
The larger value is 89.
与【例1-1】和【例1-2】不同,这段程序由两个函数组成,一个是主函数,这是每个C程序必须有的;另一个是用户自己定义的函数maxValue。
在主函数中,首先定义了两个整型变量x、y,然后调用标准输出函数printf显示一个要求用户输入两个整数的提示信息“Enter 2 integers:”,随后调用标准输入函数scanf接收用户通过键盘输入的两个整数值,并把它们分别赋给变量x和变量y,最后调用maxValue函数求得两个整数中较大的一个,回送给main函数并赋值到变量z中,并再次利用printf函数输出最终的结果。
上述3个例子中的语法和语义将在以后章节中介绍,这里仅仅归纳出C程序结构的特点。
(1)任何一个C程序都是由一个或若干个函数构成的,其中必须包含一个名为main的主函数。main函数将由系统自动调用,是整个程序执行的起始点。
(2)C程序中的函数被分成两类:一类是系统定义的标准函数,如printf和scanf。在调用它们之前,需要使用C语言提供的编译预处理命令#include将含有相应标准函数原型声明的头文件嵌入到程序中;另一类是用户自定义的函数,如maxValue。
(3)C程序的执行采用顺序执行的方式,函数体内的语句顺序执行,只有if和for等语句可以改变语句的执行顺序。
(4)程序中每一条语句都必须描述出具体的操作,包括用于算术运算和比较运算的操作,用于变量赋值的操作,用于控制程序执行顺序的操作。其中,变量代表存储器,赋值就是修改存储器的内容。
为了提高程序的清晰度,便于程序的阅读、理解和维护,建议在书写C程序源代码的时候遵循以下几个原则。
(1)如果一个程序包含多个函数定义,函数与函数之间空一行。
(2)表示函数体的一对括号{…}可以按照如下方式书写:
<函数返回类型> <函数名>(<参数表>)
{
…
}
(3)在函数体中,变量定义与执行语句之间需要添加一个空行。
(4)尽量做到一条语句写在一行中,一行也只写一条语句。
(5)采用缩进方式书写语句,即内层语句较外层语句向右缩进两列。
按照上述规范的书写方式来组织程序是程序员必须养成的良好习惯。就如同汉字的书写应该“横平竖直”一样,标准的程序书写方式是正规程序员必备的专业素质之一。
1.2.2 运行C程序的基本过程
C语言是一种编译型的程序设计语言,即C语言描述的程序不能直接运行,它必须翻译成机器语言程序,才能在计算机上运行。一个C 语言程序从编写到运行的基本过程如图1-3所示。

图1-3 C程序的基本运行过程
下面分别阐述各阶段的主要任务。
(1)编辑阶段。使用一个具有编辑功能的软件来编写C程序的源代码,并以纯文本的形式保存成扩展名为.c 或.cpp 的文件。通常将这个文件称为 C 源程序文件。Visual Studio 和Dev-C++等集成开发环境都提供了功能强大的编辑器,开发者应该熟悉这些工具的使用方法。
(2)编译阶段。编译阶段的任务是将编辑好的C源程序翻译成二进制目标代码。任何一个C语言开发环境都会提供用于编译C源程序的编译程序。一旦运行编译程序,它就会对C源程序进行检查。如果发现错误,就会给出相应的错误提示。编译程序接收的文件是扩展名为.c/.cpp的C源文件,编译成功后产生的是拓展名为.obj的二进制目标文件。
(3)连接阶段。经过编译阶段产生的二进制目标文件是一个需要重新定位的程序模块。一个完整的、可运行的C程序可能由多个目标程序模块和标准函数构成。集成开发环境提供了标准函数库文件(以.lib 为扩展名)和连接程序。连接程序的主要任务就是将多个扩展名为.obj的目标文件和扩展名为.lib函数库文件,连接成可执行程序,保存为一个扩展名为.exe的可执行程序文件。
(4)运行阶段。在扩展名为.exe的可执行程序文件生成后,就可以在计算机系统上运行这个程序了。
实际上,从把一个编写好的C程序代码输入到计算机开始,到最终能够正确运行这个程序,往往需要多次反复地进行编辑、编译、连接和运行。例如,当编译程序发现语法错误,需要重新进入编辑阶段,并根据编译程序提供的错误提示对源程序进行修改;当出现连接错误时,也需要检查源程序,以便确定是否由于书写错误造成寻找不到需要连接的程序模块;当出现运行错误时,则需要根据错误类别推测产生错误的原因,然后对源程序做出相应的修改。每次对源程序的任何改动都需要重新进行编译、连接和运行。
初次接触程序设计的人可能会感觉:运行C程序是一个比较复杂的过程,特别是需要记忆各种操作命令,这对于很多人来说是一件很烦心的事情。实际上,目前市场上流行着许多功能强大、操作方便的集成开发环境,它们将上述运行程序的各个环节集成在一起,使得运行程序变得很简单,例如,Visual Studio、Dev-C++等就是深受人们青睐的C程序集成开发环境。本书将主要介绍Visual Studio 2010和Dev-C++ 5.1开发环境,其他版本的开发环境与之有很多相似之处,有兴趣的读者可以参考相关的资料。
1.2.3 使用Visual Studio 2010 集成环境开发C程序的过程
微软公司开发的可视化编程套件Visual Studio 2010可以用在Windows环境下开发C程序或C++程序。在这个集成环境中,囊括了创建、编辑、编译、连接和调试C/C++程序的所有功能。同时,面向Windows环境的软件开发,提供了基于向导的可视化编程工具,是一种能够方便、快捷地开发C/C++程序的软件开发工具。
本节将以【例1-3】的程序为例,介绍在Visual Studio 2010环境下编辑、编译、连接和运行C语言程序的基本过程。关于Visual Studio 2010环境的使用方法,请参阅附录C。
使用Visual Studio 2010环境开发并运行一个C程序大致需要经过以下几个步骤。
(1)对于安装了Visual Studio 2010中文专业版的计算机,其执行程序是devenv.exe;往往安装在目录C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE下面。通常可以在桌面图标或程序菜单中找到Microsoft Visual Studio 2010的程序入口。启动该程序之后,可以看到如图1-4所示的用户界面。

图1-4 Visual Studio 2010环境用户界面
在Visual Studio 2010环境中,采用项目工程Project来管理正在开发的软件。每个项目工程中通常包含若干个源程序文件和数据文件。为了开发【例 1-3】所示的简单程序,首先需要建立一个新的项目工程Project。为此,应选择“文件”→“新建”→“项目”命令,在如图1-5所示的对话框中输入新的项目工程名(如MyProc),并指定存储工程文件的文件夹,属于该工程的所有文件将保存在该文件夹中。
在图1-5所示的右侧列表中,需要指定程序的种类,这里应该选择“Win32控制台应用程序”选项,输入/输出都通过控制台进行。其他选项用于开发各种形式的Windows程序。随后,用户单击“确定”按钮,进入Win32应用程序向导,选择“下一步”按钮,将出现如图1-6所示的对话框,提示用户选择程序类型。对于C程序的开发者,应该在“附加选项”中勾选“空项目”选项,然后单击“完成”按钮,即可完成项目工程MyProc的创建。此时,系统回到如图1-4所示的用户界面,左侧的窗口中可以看到刚刚建立的工程MyProc的详细目录。

图1-5 工程创建对话框

图1-6 应用程序向导对话框
(2)在项目工程建立之后,开始创建C语言的源程序文件。这时,需要选择“项目”→“添加新项”命令,将看到如图1-7所示的对话框。
在文件创建对话框中,可以为当前项目工程“MyProc”创建各种文件。在中央的栏目中需要指定文件的类型,对于C/C++程序,用户应该选择“C++文件(.cpp)”选项,并且在下面的名称编辑框中输入文件名。由于Visual Studio环境主要用于开发C++程序,文件扩展名的默认值是.cpp,因此,对于C程序的编制,应该指定其扩展名为.c,如C1_3.c。

图1-7 文件创建对话框
(3)工程与文件创建完毕,从用户界面左侧的窗口中可以看到创建好的项目工程MyProc与C程序文件C1_3.c。双击文件图标,右侧将展示出文件编辑窗口。在编辑窗口内,输入程序代码,如图1-8所示。

图1-8 进入文件编辑的Visual Studio 2010用户界面
(4)编辑完成后,选择“调试”→“开始执行”命令或按“Ctrl+F5”组合键,如图 1-9所示。它将提示开发者确认程序的生成,随后启动程序的编译、连接和运行。这个命令中包括了将文件C1_3.c编译成目标文件C1_3.obj;然后将该文件和程序中引用的库文件相连接,构造出执行程序文件MyProc.exe;最后,在控制台启动该程序的运行。所有这些文件都被置于本工程所属的文件夹中,可以通过资源管理器浏览。

图1-9 编辑完成后,选择“调试”→“开始执行”命令时的用户界面
用户界面最下方的输出窗口中将展示出程序编译和连接的过程信息。如果编译过程中发现C程序中存在错误,则会在该窗口中显示错误提示信息。用鼠标双击错误信息所在行,系统将在编辑窗中指出可能存在错误的语句。
(5)正常情况下,运行的程序MyProc.exe,通过控制台显示输出信息,接收用户输入,如图1-10所示,该程序提示用户输入两个整数。

图1-10 控制台窗口中MyProc.exe程序运行画面
如果此时用户输入了49 98,将得到如图1-11所示的运行结果。

图1-11 控制台窗口中的输入/输出信息
至此,程序运行结束。所有的输入/输出信息都会显示在控制台窗口中。用户可以按任意键来返回用户界面,继续程序的编制和修改。程序运行过程中也可以按“Alt+Tab”组合键在用户界面和控制台窗口之间切换。
在上述过程中,使用Visual Studio 2010开发环境对【例1-3】的C程序(C1_3.c)进行了编译、连接和运行,生成了C1_3.obj、MyProc.exe等文件,保存在该工程所属的文件夹内。其中,MyProc.exe是最终生成的执行程序,用于完成C1_3.c文件中所描述的计算。
上述操作过程仅叙述了最简单的程序编译、运行过程,未涉及排错处理和复杂的程序结构。关于Visual Studio 2010环境对于程序调试过程的支持,请参考2.4节的介绍和附录C。
1.2.4 使用Dev-C++ 集成环境开发C程序的过程
Dev-C++ 5.1是Bloodshed公司开发的一套专门用于开发C/C++程序的集成环境。在这个集成环境中,囊括了创建、编辑、编译、连接和调试C/C++程序的所有功能,是一种能够方便、快捷地开发C/C++程序的有效工具。
下面通过运行【例1-3】的程序,介绍在Dev-C++环境下运行C程序的基本过程。
(1)启动Dev-C++环境之后,将可以看到如图1-12所示的用户界面。

图1-12 Dev-C环境用户界面
(2)创建一个新文件或打开一个已经存在的C源文件。
在这里,可以选择“File”→“New”→“Source File”命令创建一个新文件,如图1-13所示,或者选择“File”→“Open”命令打开一个已经存在的C源文件。

图1-13 创建或打开C源文件

图1-14 输入C源代码的用户界面
(3)如果是新文件,可将源程序代码输入到Untitle1标识的区域中。在这里,输入【例1-3】的源程序代码,如图 1-14 所示。如果在此之前,这个程序没有被保存过,则需要选择“File”→“Save as”命令,以便为新文件命名并将输入的程序源代码保存起来(如C1_3.c)。否则,可以直接选择“File”→“Save”命令或按“Ctrl+S”组合键将修改后的程序源代码保存在当前文件。
(4)选择“Execute”→“Compile”命令或按“F9”键将启动编译程序完成对C源文件的编译,如图1-15所示。如果出现语法错误,将在最下面的Compile Log框中显示编译程序给出的提示信息。

图1-15 C源程序的编译界面
(5)如果编译成功,选择“Execute”→“Run”命令即可启动该程序的运行。正常情况下,可以看到如图1-16所示的等待用户输入界面。
当用户通过键盘输入48 89后,按回车键即可看到如图1-17所示的程序运行结果,用户按“F”键也可以查看到这个结果。

图1-16 等待用户输入的界面

图1-17 展示程序运行结果的界面
上述内容只涉及运行一个C源程序的最简单过程,有关Dev-C++开发环境更加详细的内容请参阅附录D。