
5.2 表达式与运算符
什么是表达式?简单地说,表达式就是用来表示我们想要如何对某个值执行运算的一种式子。前面在讲函数和返回值的时候已经用到了表达式。本章要关注的是C语言里面比较基础的算术运算符,包括加法、减法、乘法与除法运算符。这些运算符在其他编程语言里面也很常见。另外,我们还要学习C语言里面的另一些运算符,包括自增/自减运算符、关系运算符(也称比较运算符)、逻辑运算符、位运算符等。然后,我们要学习各种形式的赋值运算符。最后,我们要了解C语言里面的几个特殊运算符,例如条件运算符与序列运算符(也称逗号运算符),这些运算符在其他编程语言里面不太常见。
本章要讲的表达式是由一个或多个值搭配运算符而构成的。表达式可以作为一条完整的语句单独出现,也可以与其他表达式一起,形成一条复杂的语句。某些运算符可以施加在一条表达式上,另一些运算符则用来连接多个表达式,这些表达式可以是简单的表达式,也可以是复杂的表达式:
□5这样的字面值是一条字面表达式(literal expression),该表达式的求值结果就是5本身。
□5+8这样的算式是一条算术表达式(arithmetic expression),它由两个简单的表达式(也就是5与8这两个字面量所分别形成的两条字面表达式)与一个算术运算符(也就是加法运算符)构成。该表达式的求值结果为13。
□5+8-10这样的表达式比前面两种都复杂。它实际上是由两条表达式(也就是算术表达式5+8与字面表达式10)及一个算术运算符(也就是减法运算符)组合而成的。程序需要先求出第一条表达式的值,然后在这个值与第二条表达式的值之间,做减法运算。
□5;这样的写法是一条表达式语句(expression statement),这条语句里面只有一个表达式(也就是字面表达式5),只要求出了这个表达式的值,这条语句就算执行完了,程序可以继续执行下一条语句。还有一种形式的表达式语句更有意义,也就是aValue=5;这样的语句,这条语句里面有两个表达式需要求值,第一个表达式是字面表达式5,求出这个表达式的值之后,程序还需要对aValue=5这个赋值表达式求值,为此,它需要将赋值运算符(也就是=号)右边的值赋给左边的aValue变量。
表达式里面的值,可以是下面三种值之一:
□字面常量
□变量值或常量值
□调用某函数后所得到的返回值
下面这条表达式把这三种值全都用了一遍:

考虑下面这样一条语句:

这条语句实际上需要执行5项操作:
□从aValue变量中获取该变量的值。
□调用feetToInches()函数。
□把字面值5与aValue的值相加,得到一个中间结果。
□将这个中间结果与调用函数所得到的结果相加,得到另一个中间结果。
□把刚才得到的中间结果赋给aLength变量。
还有一种写法也能得到相同的结果,也就是把刚才那条复杂的语句拆分成下面三条简单的语句:

这种写法分别对不同的表达式求值,并将求值结果与aLength当前的值相加,然后赋回给aLength变量本身。这么写总共需要执行三次赋值。这种写法不需要计算临时的中间结果,因为我们明确地写出了每一个步骤,我们先把当前这个步骤的结果记录到aLength里面,然后再用这个值去执行下一个步骤。
下面我们编写一个简单的程序calcLength.c,这个程序把刚才说的那些简单表达式与复杂表达式全都演示了一遍。代码如下:


这个程序会把三个值加起来以确定aLength的取值,这三个值分别是字面值5、变量值aValue以及调用feetToInches()函数所返回的值。然后,程序把aLength的值打印到控制台。这个程序本身并没有太大的作用,因为我们看不出要计算的是个什么结果,也不清楚为什么要选用这样几个值来计算这个结果。该程序的重点在于:同一个aLength变量,可以有两种计算方式。除了写一条复杂的语句把三个值加起来,我们还可以分别采用三条简单的语句来完成。
现在请你创建一个名叫calcLength.c的文件,把刚才那段代码录入该文件,然后保存并编译,最后运行程序。你应该会看到这样的输出结果。

大家都看到了,用三条语句来计算aLength要比用一条语句更啰嗦,但这并不意味着篇幅比较长(或比较短)的那种写法是错误的,也不意味着其中某个写法比另一个高明。如果要做的计算比较简单,那么合起来写到一条语句里面可能较为清晰。如果要做的计算比较复杂,那还是拆分成多个步骤更好。具体怎样写需要仔细思考,你需要在缩短代码行数与提升清晰程度之间寻找平衡。如果二者不能兼顾,那宁可选择清晰一些但是篇幅稍长的写法。