C和指针:良好的程序风格和文档将使程序更容易阅读和维护

毫无疑问,学习一门编程语言的基础知识不如编写程序有趣 。但是,不知道语言的基础知识会使你在编写程序时缺少乐趣 。
2.1 环境在ANSI C的任何一种实现中,存在两种不同的环境 。第1种是翻译环境(translation environment),在这个环境里,源代码被转换为可执行的机器指令 。第2种是执行环境(execution environment),它用于实际执行代码 。标准明确说明,这两种环境不必位于同一台机器上 。例如,交叉编译器(cross compiler)就是在一台机器上运行,但它所产生的可执行代码运行于不同类型的机器上 。操作系统也是如此 。标准同时讨论了独立环境(freestanding environment),就是不存在操作系统的环境 。你可能在嵌入式系统中(如微波炉控制器)遇到这种类型的环境 。
2.1.1 翻译【C和指针:良好的程序风格和文档将使程序更容易阅读和维护】翻译阶段由几个步骤组成,组成一个程序的每个(有可能有多个)源文件通过编译过程分别转换为目标代码(object code) 。然后,各个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序 。链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它也可以搜索程序员个人的程序库,将其中需要使用的函数也链接到程序中 。图2.1描述了这个过程 。

C和指针:良好的程序风格和文档将使程序更容易阅读和维护

文章插图
 
图2.1 编译过程
编译过程本身也由几个阶段组成,首先是预处理器(preprocessor)处理 。在这个阶段,预处理器在源代码上执行一些文本操作 。例如,用实际值代替由#define指令定义的符号以及读入由#include指令包含的文件的内容 。
然后,源代码经过解析(parse),判断它的语句的意思 。第2个阶段是产生绝大多数错误和警告信息的地方 。随后,便产生目标代码 。目标代码是机器指令的初步形式,用于实现程序的语句 。如果我们在编译程序的命令行中加入了要求进行优化的选项,优化器(optimizer)就会对目标代码进一步进行处理,使它效率更高 。优化过程需要额外的时间,所以在程序调试完毕并准备生成正式产品之前一般不进行这个过程 。至于目标代码是直接产生的,还是先以汇编语言语句的形式存在,然后再经过一个独立的阶段编译成目标文件,对我们来说并不重要 。
一、文件名约定尽管标准并没有制定文件的取名规则,但大多数环境都存在你必须遵守的文件名命名约定 。C源代码通常保存于以.c扩展名命名的文件中 。由#include指令包含到C源代码的文件被称为头文件,通常具有扩展名.h 。
至于目标文件名,不同的环境可能具有不同的约定 。例如,在UNIX系统中,它们的扩展名是.o,但在MS-DOS系统中,它们的扩展名是.obj 。
二、编译和链接用于编译和链接C程序的特定命令在不同的系统中各不相同,但许多都和这里所描述的两种系统差不多 。在绝大多数UNIX系统中,C编译器被称为cc,它可以用多种不同的方法来调用 。
1.编译并链接一个完全包含于一个源文件的C程序:
cc program.c这条命令产生一个称为a.out的可执行程序 。中间会产生一个名为program.o的目标文件,但它在链接过程完成后会被删除 。
2.编译并链接几个C源文件:
cc main.c sort.c lookup.c当编译的源文件超过一个时,目标文件便不会被删除 。这就允许你对程序进行修改后,只对那些进行过改动的源文件进行重新编译,如下一条命令所示 。
3.编译一个C源文件,并把它和现存的目标文件链接在一起:
cc main.o lookup.o sort.c4.编译单个C源文件,并产生一个目标文件(本例中为program.o),以后再进行链接:
cc –c program.c5.编译几个C源文件,并为每个文件产生一个目标文件:
cc –c main.c sort.c lookup.c6.链接几个目标文件:
cc main.o sort.o lookup.o上面那些可以产生可执行程序的命令均可以加上“-o name”这个选项,它可以使链接器把可执行程序保存在“name”文件中,而不是“a.out” 。在缺省情况下,链接器在标准C函数库中查找 。如果在编译时加上“-lname”标志,链接器就会同时在“name”的函数库中进行查找 。这个选项应该出现在命令行的最后 。除此之外,编译和链接命令还有很多选项,请查阅你所使用的系统的文档 。
用于MS-DOS和windows的Borland C/C++ 5.0有两种用户界面,你可以分别选用 。Windows集成开发环境是一个完整的独立编程工具,它包括源代码编辑器、调试器和编译器 。它的具体使用不在本书的范围之内 。MS-DOS命令行界面则与UNIX编译器差不太多,只是有下面几点不同:


推荐阅读