
2.5 执行顺序
程序执行时,首先要找到main()函数并进入该函数块,然后才开始执行其中的语句。如果遇到了某条函数调用语句,那么会发生下面这四个步骤:
1.如果要调用的那个函数带有参数,那么程序需要把函数调用语句中提到的实际值赋给那个函数的相关参数。
2.程序跳转到那个函数,并开始执行其函数块中的代码。
3.程序一直往下执行,直到遇见return语句(返回语句),或达到函数块的末尾(也就是遇到函数最后的那个右花括号)为止。
4.程序跳回(或者说返回)主调函数,并继续执行第1步中提到的那条函数调用语句的下一条语句。
如果在执行第2步的过程中又遇到了函数调用语句,那么就重复以上步骤。
下面这张图演示了程序在执行各个级别的函数调用语句时所经历的调用/返回顺序。程序必须通过函数调用语句来进入某个函数,而不能直接转入另一个函数。C语言不允许这样做。

下面解释图中的每一个步骤。
1.操作系统调用这个程序,并从它的main()函数开始执行。
2.main()函数调用printGreeting()函数,于是程序跳转到后者的函数块,并执行其中的语句。
3.printGreeting()函数调用printAGreeting()函数,于是程序跳转到后者的函数块,并执行其中的语句。
4.printAGreeting()函数把函数块中的语句执行完毕后,将控制权返还给print-Greeting()函数。
5.printGreeting()函数调用printAComma()函数,于是程序跳转到后者的函数块,并执行其中的语句。
6.printAComma()函数把函数块中的语句执行完毕后,将控制权返还给print-Greeting()函数。
7.printGreeting()函数调用printAnAddressee()函数,于是程序跳转到后者的函数块,并执行其中的语句。
8.printAnAddressee()函数把函数块中的语句执行完毕后,将控制权返还给printGreeting()函数。
9.printGreeting()函数调用printANewline()函数,于是程序跳转到后者的函数块,并执行其中的语句。
10.printANewline()函数把函数块中的语句执行完毕后,将控制权返还给print-Greeting()函数。
11.printGreeting()函数把函数块中的语句执行完毕后,将控制权返还给main()函数。
12.按照main()函数的定义,main()函数必须返回一个整数值,因此,它现在该执行return 0;语句了,这条语句会令main()函数结束运行,并把控制权返还给操作系统。
只要程序从某个函数中返回,它就会由早前进入该函数时的位置开始继续往下执行。
如果return 0;或return;语句的后面还有其他语句,那么不会执行到那些语句。
大家可能注意到了,目前为止所举的例子都是先定义某个函数,然后再调用它。如果想按照相反的顺序来编程(也就是说,想把调用某个函数的语句先写出来,以后再定义这个函数),那该怎么办?为了解决这个问题,我们需要明白什么叫作函数声明(function declaration)。