2.2 运算符和表达式

C语言的运算符不仅具有不同的优先级,而且还有一个特点,就是它的结合性。在表达式中,各运算量参与运算的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的制约,以便确定是自左向右进行运算还是自右向左进行运算。这种结合性是其他高级语言的运算符所没有的,因此也增加了C语言的复杂性。C语言的运算符如表2-3所示。

表2-3 运算符分类表

续表

表达式是由常量、变量、函数和运算符组合起来的式子。表达式的值与类型等于计算表达式所得结果的值和类型。表达式求值按运算符的优先级和结合性规定的顺序进行。单个的常量、变量、函数可以看作是表达式的特例。指针运算符和一些特殊运算符将在后续章节中介绍。

2.2.1 算术运算符和算术表达式

(1)基本的算术运算符

①加法运算符“+”:加法运算符为双目运算符,即应有两个量参与加法运算,如a+b,4+8等,具有左结合性。

②减法运算符“-”:减法运算符为双目运算符,但“-”也可作负值运算符,此时为单目运算,例如,-x,-5等具有左结合性。

③乘法运算符“*”:双目运算具有左结合性。

④除法运算符“/”:双目运算具有左结合性。参与运算量均为整型时,结果也为整型,舍去小数。例如,10/7结果为1,2/5结果为0,1/3+1/3+1/3的结果也是0。如果运算量中有一个是实型,则结果为双精度实型。

⑤取模运算符“%”:双目运算,具有左结合性。要求参与运算的量均为整型。运算的结果为两数相除后的余数。例如,5%3的值为2。

(2)算术表达式和运算符的优先级和结合性

算术表达式:用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子;单独的常量、变量、函数也是表达式。

以下是算术表达式的例子:

a+b  (a*2)/c  (x+r)*8-(a+b)/7

++i  sin(x)+sin(y)  (++i)-(j++)+(k--)

书写表达式时应注意与数学公式的区别。例如:

数学式的C语言表达式为(x+y)/(a+b),为与数学运算要求一致可用括号调整运算的先后顺序。

数学式的C语言表达式为(-b+sqrt(b*b-4*a*c))/(2*a)。

运算符的优先级:C语言中,运算符的运算优先级共分为14级。1级最高,14级最低。在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。

运算符的结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如:算术运算符的结合性是自左至右,即先左后右。例如:表达式x-y+z,y应先与-号结合,执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。最典型的右结合性运算符是赋值运算符。如x=y=z,由于=的右结合性,应先执行y=z再执行x=(y=z)运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。

(3)自增、自减运算符

自增1,自减1运算符:自增1运算符记为++,其功能是使变量的值自增1。自减1运算符记为--,其功能是使变量值自减1。

自增1,自减1运算符均为单目运算,都具有右结合性。可有以下几种形式:

++i:i自增1后再参与其他运算;

--i:i自减1后再参与其他运算;

i++:i参与运算后,i的值再自增1;

i--:i参与运算后,i的值再自减1。

例如:

int j=5,k=5,m,n;

m=j++;  //相当于m=j;j=j+1;运算后j的值为6,m的值为5

n=++k;  //相当于k=k+1;n=k;运算后k的值为6,n的值为6

【例2.5】阅读程序,分析结果加深对各种算术运算的理解。

运行结果如图2-6所示:

图2-6 例2.5运行结果

说明:

i的初值为8,第5行i加1后输出故为9;第6行减1后输出故为8;第7行输出i为8之后再加1(为9);第8行输出i为9之后再减1(为8);第9行输出-8之后再加1(i为9),第10行输出-9之后再减1(i为8)。输出的值与i值的变化如表2-4所示。

表2-4 输出的值与i值的变化

2.2.2 关系运算符和关系表达式

关系运算是逻辑运算中比较简单的一种。所谓“关系运算”实际上就是“比较运算”,将两个值进行比较,判断比较的结果是否符合给定的条件。在程序中经常需要比较两个量的大小关系,以决定程序下一步的工作。

(1)关系运算符及其优先级

C语言中的关系运算符如表2-5所示。

表2-5 C语言中的关系运算符

关系运算符都是双目运算符,其结合性均为左结合。关系运算符的优先级低于算术运算符,高于赋值运算符。在六个关系运算符中,<,<=,>,>=的优先级相同,高于==和!=;==和!=的优先级相同。

(2)关系表达式

关系表达式是指用关系运算符将两个表达式连接起来的有意义的式子。

关系表达式的一般形式为:

表达式 关系运算符 表达式

例如:x>y,5>3,三角形两边之和大于第三边(a+b)>c,都是合法的关系表达式。由于表达式也可以是关系表达式。因此也允许出现嵌套的情况,例如:(a!=b)<(c>d),b<c+d!=a等。

在进行关系运算时,需要注意以下几点:

关系表达式的结果是一个逻辑值,在C语言中逻辑值“真”用“1”表示,“假”用“0”表示。若关系表达式成立,则结果为1,否则,结果为0。例如:5>3成立,逻辑值为真,结果为1。

关系运算符的优先级低于算术运算符,高于赋值运算符=。

在C语言中,符号=用作赋值运算符,因而用==表示等于关系。另外,表示大于等于、小于等于、不等于所用的表示方法也和数学公式中的不同。

【例2.6】阅读程序,分析结果加深对各种关系运算的理解。

运行结果如图2-7所示。

图2-7 例2.6运行结果

2.2.3 逻辑运算符和逻辑表达式

(1)逻辑运算符及其优先级

关系表达式只能描述单一条件,例如x>=0,如果需要描述x>=0同时x<10,就要借助逻辑表达式了。

C语言中提供了三种逻辑运算符,如表2-6所示。

表2-6 C语言中的三种逻辑运算符

逻辑与运算符“&&”和逻辑或运算符“||”均为双目运算符,具有左结合性。逻辑非运算符“!”为单目运算符,具有右结合性。逻辑运算符和其他运算符优先级的关系如图2-8所示。

图2-8 运算符优先级

按照运算符的优先顺序可以得出:

a>b&&c>d  等价于  (a>b)&&(c>d)

!b==c||d<a  等价于  ((!b)==c)||(d<a)

a+b>c&&x+y<b  等价于  ((a+b)>c)&&((x+y)<b)

(2)逻辑运算的值

逻辑运算的值分为“真”和“假”两种,用“1”和“0”来表示。表2-7为逻辑运算的“真值表”。用它表示当a和b的值为不同组合时,各种逻辑运算所得到的值。

表2-7 逻辑运算真值表

其求值规则如下:

①逻辑与运算“&&”:参与运算的两个量都为真时,结果才为真,否则为假。

②逻辑或运算“||”:参与运算的两个量只要有一个为真,结果就为真;两个量都为假时,结果为假。

③逻辑非运算“!”:参与运算量为真时,结果为假;参与运算量为假时,结果为真。

【例2.7】阅读程序,分析结果加深对各种逻辑运算的理解。

运行结果如图2-9所示。

图2-9 例2.7运行结果

虽然C语言编译在给出逻辑运算值时,以“1”代表“真”,“0”代表“假”。但反过来在判断一个量是为“真”还是为“假”时,以“0”代表“假”,以非“0”的数值作为“真”。

(3)逻辑表达式

逻辑表达式的一般形式为:

表达式 逻辑运算符 表达式

其中,表达式可以又是逻辑表达式,从而组成了嵌套的情形。

例如:(a&&b)&&c,根据逻辑运算符的左结合性,上式也可写为:a&&b&&c。

逻辑表达式的值是式中各种逻辑运算的最终值,以“1”和“0”分别代表“真”和“假”。

2.2.4 条件运算符和条件表达式

如果在条件语句中,只执行单个的赋值语句时,常可使用条件表达式来实现。条件运算符为“?:”,它是一个三目运算符,即有三个参与运算的量。

由条件运算符组成条件表达式的一般形式为:

表达式1 ?表达式2 :表达式3

其执行的过程是:当表达式1的值为真,则以表达式2的值作为条件表达式的值,否则以表达式3的值作为条件表达式的值。例如:当x=6,y=7时,条件表达式x>y?x:y的结果为7,即取变量y的值。

使用条件表达式时,还应注意以下几点:

①条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值符;

②条件运算符“?”和“:”是一对运算符,不能分开单独使用;

③条件运算符的结合方向是自右至左。

例如:a>b?a:c>d?c:d应理解为a>b?a:(c>d?c:d)。这也就是条件表达式嵌套的情形,即其中的表达式3又是一个条件表达式。

【例2.8】从键盘输入任意两个整数,输出大的一个。

运行结果如图2-10所示。

图2-10 例2.8运行结果

2.2.5 赋值运算符和赋值表达式

(1)一般赋值运算符

简单赋值运算符和表达式:简单赋值运算符记为“=”。由“=”连接的式子称为赋值表达式。其一般形式为:

变量=表达式;

例如,x=a+b,赋值表达式的功能是计算表达式的值再赋予左边的变量。赋值运算符具有右结合性。

在C语言程序中,凡是表达式可以出现的地方均可出现赋值表达式。例如,式子x=(a=5)+(b=8)是合法的。它的意义是把5赋予a,8赋予b,再把a,b相加,和赋予x,故x应等于13。

(2)复合赋值运算符

在赋值符“=”之前加上其他二目运算符可构成复合赋值符。例如,+=,-=,*=,/=,%=,<<=,>>=,&=,∧=,|=

构成复合赋值表达式的一般形式为:

变量 双目运算符=表达式

它等效于:

变量=变量 运算符 表达式

例如:

a+=5 等价于a=a+5

x*=y+7 等价于x=x*(y+7)

r%=p 等价于r=r%p

复合赋值运算符这种写法对于初学者可能不习惯,但十分有利于编译处理,能提高编译效率并产生质量较高的目标代码。

2.2.6 逗号运算符和逗号表达式

在C语言中逗号“,”也是一种运算符,称为逗号运算符。其功能是把两个表达式连接起来组成一个表达式,称为逗号表达式。

其一般形式为:

表达式1,表达式2,…,表达式n

其求值过程是从左至右分别求各个表达式的值,并以表达式n的值作为整个逗号表达式的值。

【例2.9】阅读并运行程序,分析结果加深对各种算术运算的理解。

语句a=(b=2,++b,b+5);先执行b=2;再执行++b,此时b的值为3;最后执行b+5,b的值为8;将8赋值给变量a,运行结果如图2-11所示。

图2-11 例2.9运行结果