读程序的一个方法
程序代码:
# include <stdio.h> void max(int a,int b) { if (a>b) printf("haha!\n"); else printf("jiji\n!"); } int main(void) { int i,j; scanf("i=%d,j=%",&i,&j); max(i,j); return 0; }
上面是一个简单的C程序,麻雀虽小,然而五脏俱全,下面讲解一下如何读程序。
用C代码写的程序,必定有一个程序的入口点,一般的编译器统一为叫main()的函数,所以我们首先要找到这个入口点,即在代码中寻找main()函数。
现在我们找到了,它在代码的后部,被声明为int main(void)。这个声明的意思,表示这是一个函数,它将会返回一个int数据给调用者(因为是程序的入口点,调用这个程序的必定是操作系统,故这是返回给操作系统的东西,如果不是涉及操作系统特殊功能的程序,操作系统得到这种返回数据是没有什么用的。什么情况下有用呢?在DOS的批处理流程中,可以编写批处理程序根据命令的返回值执行后续命令。这种批处理程序,在Windows中被称为脚本),括号扩着的是这个函数的参数列表,void是没有的意思(既可以void参数,也可以void返回值)。
函数声明之后,必然有一对花括号,把这个函数的所有代码都括住,这样一段范围之内的代码,被称为一个代码“块”(也叫“函数体”),是一个局部的整体,执行相对独立的程序功能。先扫一眼这块代码大致从哪里到哪里。按照推荐,书写良好的代码块,不应该太长,执行太多的功能。
C语言的函数体,开头处通常是变量声明。在这里,我们看到int i,j的声明语句,意思是告诉编译器,在这块程序代码中,将会使用两个变量,分别叫i、j,它们都是int类型的数据,如果你(此处的你指编译器)在读入下面代码块的时候,碰到某个单词,是i或j的话,就把它视为int类型的变量处理。换句话说,如果碰到没有被声明的单词,又不是C保留字的话,则是不允许的,此时你要报告出错,停止编译,让程序设计者重新书写代码(不是任何语言都必须这样的,有些弱类型语言,就允许未经声明的变量直接使用,如BASIC)。C之所以作这样的强制类型检查,是怕程序员输入代码时的拼写错误,他可能一直都写char,但某处偶然多写了一个s,拼成chars,这种机制就能给程序员纠正错误的机会,但BASIC等不会这样做,它会视这是一个不同的变量,此时运行结果可能与设计初衷大相径庭(因此,现代VB新出现的语法机制,可以设置开关,强制变量声明)。在这里有一点是必须注意的:C是大小写敏感的语言,i和I是两个不同的变量!
继续往下看,那是一条接受输入的语句。scanf()函数不是C的标准函数(但main()是),它是在外部的、被称为库(LIB)的地方取得的一个函数,这种函数是大量程序员为丰富C程序的功能而编写的,所以这样的函数各有各的特色,不会完全一样的——MSC提供的scanf()和Turbo C提供的scanf(),在内部代码可能是不同的,甚至有不同的副作用。有些功能相同的函数,连函数名都不同。这样的库函数,必须查阅书写该函数提供者的资料,才能知道其语法、用法。C的强大功能,很大程度上是众多程序员提供了丰富的代码形成的,类似于Unix的强大,也是因此而来。这些先不谈,现在看到scanf()函数,就是在标准流文件上读入数据的函数,所谓“流文件”,先搁置一边,但要先知道,凡是使用涉及流文件的函数,都要在程序包含stdio.h的头文件,此时,我们要检查是否包含了这个文件,即程序最开始处的#include <stdio.h>,没有这个东西,编译器就不会把外部库函数编译进来,于是程序就找不到scanf()函数的二进制代码,无法运行(这就是非标准C函数的特性,必须连编外部LIB文件)。
用scanf()读入两个变量i、j的值。此处,我们看到先前声明的变量确实用到了(如果有的变量被声明之后从来没用过,编译器会出警告信息,提示你是不是漏了什么代码,为什么明明说好会出现的东西最终没出现,那通常来说是不正常的)。
读到两个变量值之后,到max(i,j)这一行。很明显,这也是一个函数,它叫max,并且带两个int类型的参数,这时,我们可能会发现,stdio.h头文件中没有声明过这样的函数(这要求我们对各种库函数的名字比较熟悉,所以库函数参考手册是必不可少的,如果没有参考手册,就直接阅读stdio.h头文件),必须找到这样的函数是怎么来的。但先别急,main()函数的代码块还没读完,不用急着找这个函数,先放在脑子里,等会再找(这就是代码块不要太长的原因,人的脑记不住太多这种悬着的东西)。
幸好,马上就到了代码块的结尾处,return 0,回应main()的函数声明,兑现了有返回值的承诺(如果没有返回值,编译器也会提醒你,承诺了东西必须做到,这是好品性,写程序如做人)。一个函数的代码块,只要执行到return语句,就会从函数体中跳出,那么这条语句后面的代码就都是废的,不会执行(我们会碰到从各种if结构中跳离函数的情形)。
先歇一会,喝壶茶,再接着说。
[ 本帖最后由 TonyDeng 于 2011-7-29 21:05 编辑 ]