现代C:概念剖析和编程实践
上QQ阅读APP看书,第一时间看更新

2.4 语句

main函数的第二部分主要由语句组成。语句是告诉编译器如何处理已经声明的标识符的指令。我们有

027-03

我们已经讨论了与printf调用相对应的行。还有其他类型的语句:for语句和return语句,以及由操作符C++表示的递增操作。下面我们将详细介绍三类语句:循环(多次执行某项操作)、函数调用(在其他地方委托执行)和函数返回(从调用函数的地方继续执行)。

2.4.1 循环

for语句告诉编译器程序应该多次执行printf行。这是C所提供的域循环C的最简单形式。它有四个不同的部分。

要重复的代码称为循环体C:它是跟在for( ... )后面的{ ... }块。其他三个部分包含在( ... )中,用分号分开:

1. 循环变量Ci)的声明、定义和初始化,这些我们已经讨论过了。这个初始化在整个for语句的其余部分之前执行一次。

2. 循环条件Ci<5),指定for循环应该持续多长时间。这告诉编译器只要i严格小于5就继续循环。循环条件在循环体每次执行之前被检查。

3. 另外一条语句(++i),在每次循环之后执行。在本例中,它每次将i的值增加1

如果把所有这些放在一起,我们要求程序执行块中的部分5次,在每次循环中将i的值分别设置为01234。事实上我们可以用i的一个特定值来标识每个循环,从而使其成为在C0, ... , 4上的循环。在C语言中有多种方法可以做到这一点,但是for是最简单、最简洁、最好用的工具。

要点2.10 域循环应该使用for语句进行编码。

除了我们刚才看到的,for语句还可以用其他几种方式编写。通常,人们将循环变量的定义放在for之前的某个地方,甚至将同一个变量用于多个循环。不要这样做:为了帮助偶尔的读者和编译器理解你的代码,重要的是要知道这个变量对于给定的for循环具有循环计数器的特殊意义。

要点2.11 循环变量应该在for的初始部分定义。

2.4.2 函数调用

函数调用是一种特殊的语句,它们暂停当前函数的执行(在开始时,通常是main),然后将控制权交给指定的函数。在我们的例子中:

028-01

调用的函数是printf。函数调用通常不仅提供函数名,还提供参数。在这里,参数是一长串字符:i, A[i]A[i]*A[i]。这些参数的被传递给函数。在本例中,这些值是printf要打印的信息。这里的重点是“值”:虽然i是一个参数,但是printf永远不能改变i本身。这种机制称为按值调用。其他编程语言也有按引用调用,它是一种被调用的函数可以改变变量值的机制。C没有实现按引用传递,但是它有另一种机制来将变量的控制传递给另一个函数:通过获取地址和发送指针。我们稍后会看到这些机制。

2.4.3 函数返回

main中的最后一个语句是return。它告诉main函数在完成后返回到调用它的语句。在这里,由于main的声明中有int,所以return必须int类型的值发送回调用语句。在本例中,这个值是EXIT_SUCCESS

即使我们看不到它的定义,printf函数也必须包含一个类似的return语句。我们在第17行调用函数时,main中语句的执行被暂时挂起。程序在printf函数中继续执行,直到遇到return。从printf返回后,main中的语句将从停止的地方继续执行。

图2.1展示了小程序的执行过程:它的控制流。首先,平台提供的流程启动例程(左边)调用用户提供的函数main(中间)。然后,调用右边的printf,它是C库函数C的一部分。一旦遇到return,控制返回到main,当到达main中的return时,它返回到启动例程。从程序员的角度来看,后面的控制转移代表程序执行结束。

029-01

图2.1 执行一个小程序

总结
  • C区分程序的词法结构(标点符号、标识符和数字)、语法结构(句法)和语义(含义)。
  • 必须声明所有标识符(名称),以便我们知道它们所表示的概念的特性。
  • 所有的对象(我们处理的事物)和函数(我们用来处理事物的方法)都必须定义。也就是说,我们必须详细说明它们是如何产生的,以及它们在哪里。
  • 语句指示事情将如何完成:循环(for)重复某些任务的变化,函数调用(printf (...))将任务委托给函数,函数返回(return something;)返回调用它们的位置。