C语言程序设计基础教程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.3 运算符和表达式

运算符是表示某种操作的符号,其操作的对象为操作数,根据运算符操作的操作数个数可把运算符分为单目运算符、双目运算符和三目运算符。用运算符把操作数按照C语言的语法规则连接起来的式子称为表达式,如表达式5+6中+运算符表示求5和6这两个操作数的和,这里的+运算符属于双目运算符。C语言为了加强对数据的表达、处理和操作能力,提供了大量的运算符和丰富的表达式类型。

3.3.1 算术运算符及其表达式

1.加法运算符(+)

双目运算符,即应有两个量参与加法运算。例如,a+b、4+8等。

说明:也可以作为正号运算符,此时为单目运算,例如,+2。

2.减法运算符( - )

双目运算符,例如x-y、14-m等。

说明:也可作为负号运算符,此时为单目运算,例如,-x、-5等。

3.乘法运算符(*)

双目运算符,需要注意的是与数学表达式不同,C语言表达式中的乘号不能省略。

例如,数学表达式2x+y写成C语言算术表达式应该为2*x+y;否则会出错。

4.除法运算符( / )

双目运算符,C语言对除法运算做了如下规定。

(1)两个整型数相除,结果也为整型,小数部分被舍弃。例如,算术表达式5/2的值为2。

(2)只要有一个操作数为实型,则结果为double型。例如,算术表达式5.0/2的值为2.5。

5.求余运算符(%)

双目运算符,也称为“模运算符”,C语言规定求余运算中的两个操作数必须为整型;否则会提示出错。余数的正负号与被除数相关,例如,算术表达式7%4的值为3,算术表达式-7%4和-7%-4的值均为-3。

6.自增运算符(++)和自减运算符(--)

(1)自增运算符(++):使单个变量的值自动加1。

(2)自减运算符(--):使单个变量的值自动减1。

自增和自减运算符都属于单目运算符,有以下两种用法。

(1)前置运算:即运算符放在变量之前,如++a、--a。运算规则为先使变量的值加(或减)1,然后以变化后的值参与其他运算。即先加减,后运算。

(2)后置运算:即运算符放在变量之后,如a++,a--。运算规则为变量先参与其他运算,然后使变量的值加(或减)1。即先运算,后加减。

说明如下。

(1)自增和自减运算只能用于变量,不能用于常量和表达式。

例如,5++或--(a+B)等都是非法的。

(2)自增和自减运算要求操作对象的值为一个整数。

例如,若x是一个float型变量,则x++或者--x都是错误的使用方式。

3.3.2 关系运算符及其表达式

1.关系运算符

所谓关系运算实际上就是比较运算,即将两个数据进行比较,判定二者是否符合给定的关系。

C语言提供如下6种关系运算符。

(1)<:小于。

(2)<=:小于或等于。

(3)>:大于。

(4)>=:大于或等于。

(5)==:等于。

(6)!=:不等于。

所有的关系运算符都是双目运算符。

关系运算符及其优先顺序如下。

(1)前4种关系运算符(<、<=、>、>=)的优先级相同,后两种也相同。前4种高于后两种,例如“>”优先于“==”,而“>”与“<”的优先级相同。

(2)关系运算符的优先级低于算术运算符。

(3)关系运算符的优先级高于赋值运算符。

以上关系如图3-6所示。

图3-6 关系运算符的优先级关系

2.关系表达式

用关系运算符将两个数值或数值表达式连接起来的式子称为“关系表达式”,例如a>ba+b>b+c、(a=3)>(b=5)、(a>b)>(b>c)都是合法的关系表达式。

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

例如:

在本例中求出了各种关系运算符的值,字符变量以其对应的ASCII码参与运算。对于包含多个关系运算符的表达式,如k==j==i+5,根据运算符的左结合性先计算k==j。该式不成立,其值为0。再计算0==i+5,也不成立,故表达式值为0。

注意区分“==”和“=”。在C语言中“==”是关系运算符,而“=”则是赋值运算符。关系运算的结果是一个逻辑值,只有两种可能,即要么关系成立,为“真”;要么关系不成立,为“假”。由于C语言没有逻辑型数据类型,所以用1代表“真”;用0代表“假”。因而所有C语言的关系表达式的运算结果实质上是数值型(1或者0)。

例如,下面的式子都是正确的关系表达式:

说明:对于字符型数据,将其转换为字符的ASCII码,再进行大小比较。

3.3.3 逻辑运算符及其表达式

关系表达式只能描述单一条件,如x表示是一个非负数,可用关系表达式x≥0来描述。如果需要描述的条件有两个或更多,如表示x的数值范围是[0,100],即x≥0且x≤100时,则要借助逻辑表达式。

用逻辑运算符连接关系表达式或逻辑量的式子就是逻辑表达式,其中逻辑量就是值为“真”或“假”的数据。C语言规定所有的非0数据判定为“真”,只有0判定为“假”。

C语言提供如下3种逻辑运算符。

(1)&&(逻辑与):双目运算符,表示“并且”,即两个条件须同时满足。

(2)||(逻辑或):双目运算符,表示“或者”,即只需满足其中任意一个条件。

(3)!(逻辑非):单目运算符,表示“否定”,即取反。

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

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

例如:

根据逻辑运算符的左结合性,上式也可写为:

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

例如:

在本例中!x和!y分别为0,!x*!y也为0,故其输出值为0。由于x为非0,故!!!x的逻辑值为0。对x|| i && j-3式,先计算j-3的值为非0,再求i && j-3的逻辑值为1,故x||i&&j-3的逻辑值为1;对i<j&&x<y式,由于i<j的值为1,而x<y为0,故表达式的值为1。与0相与,最后为0;对i==5&&c&&(j=8)式,由于i==5为假,故值为0。该表达式由两个与运算符组成,所以整个表达式的值为0;对于式x+ y||i+j+k,由于x+y的值为非0,故整个或表达式的值为1。

与关系运算一样,逻辑运算的结果也只有“真”和“假”两种情况,即所有C的逻辑表达式的运算结果实质上也是数值型(1或者0)。逻辑运算的真值表如表3-6所示。

表3-6 逻辑运算的真值表

例如,下面的式子都是正确的逻辑表达式:

3.3.4 位运算符及其表达式

位运算是指按二进制位执行的运算,C语言提供6种位操作运算符,即&(按位与)、|(按位或)、^(按位异或)、~(取反)、<<(左移)和>>(右移)。

位运算符只能用于整型操作数,即只能用于带符号或无符号的char、short、int与long类型。

1.&

双目运算符,功能是参与运算的两数中各对应的二进位执行与运算。只有对应的两个二进位均为1时,结果位才为1;否则为0。参与运算的数以补码形式出现。

例如,9&5可写为如下算式:

可见表达式9&5的值为1。

该运算符的应用如下。

(1)清0。

若清0一个存储单元,即使其全部二进制位为0。只要找一个二进制数,其中各位符合的条件是原来数中为1的位,新数中相应位为0。然后二者执行&运算,即可达到清0目的。

例如,原数为43,即00101011。另找一个数设为148,即10010100,将二者执行按位与运算:

(2)取一个数中某些指定位。

若有一个整数a(2字节),需要取其中的低字节,只需要将a与8个1按位与即可。

(3)保留指定位。

与一个数执行按位与运算,此数在该位取1,即可保留该位。

例如,有一数84,即01010100。需要把其中从左边算起的第3、4、5、7、8位保留下来,运算如下:

a=84,b=59,a&b=16。

2.|

双目运算符,功能是参与运算的两数中对应的二进位执行或运算。只要对应的两个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。

例如,9|5的算式如下:

可见9|5=13。

3.^

双目运算符,其功能是参与运算的两个数中对应的二进位相异或。当两对应的二进位相异时,结果为1。参与运算的两个数均以补码出现。

例如,9^5可写成如下算式:

按位异或的应用如下。

(1)使特定位翻转。

假设有二进制数01111010,要使其低4位翻转,即1变0,0变1,可以将其与00001111执行异或运算。

运算结果的低4位正好是原数低4位的翻转,可见要使哪几位翻转就与其执行^运算的几位置为1即可。

(2)与0相异或保留原值。

例如,012^00=012

因为原数位中的1与0执行异或运算得1,0^0得0,故保留原数。

4.~

单目运算符,具有右结合性。其功能是按位求反参与运算数的各个二进位。

例如,~9的运算:

~(0000000000001001)

结果为1111111111110110。

5.<<

双目运算符,功能是把<<左边运算数的各个二进位全部左移<<右边数指定的位数,高位丢弃,低位补0。

例如,a<<4把a的各个二进位向左移动4位。假设a=00000011(十进制数3),左移4位后为00110000(十进制数48)。

左移1位相当于该数乘以2,左移两位相当于该数乘以2*2=4。15<<2=60,即乘了4,但此结论只适用于该数左移时被溢出舍弃的高位中不包含 1的情况。

假设以一个字节(8位)存一个整数,且a为无符号整型变量,则a=64时,左移一位时溢出的是0;而左移2位时,溢出的高位中包含1。

6.>>

双目运算符,功能是把>>左边的运算数的各个二进位全部右移>>右边的数指定的位数。

例如,设a=15,a>>2表示把000001111右移为00000011(十进制数3)。

应该说明的是有符号数在右移时符号位将随同移动,为正数时最高位补0;为负数时符号位为1,最高位补0或补1 取决于编译系统的规定(Turbo C和很多系统规定为补1)。

3.3.5 赋值运算符及其表达式

C语言中的赋值运算符都是双目运算符,主要包括以下两种。

(1)直接赋值运算符(=)。

运算规则为先求=右边的值,然后赋给=左边的变量,赋值表达式的值就是左边变量的值。例如:

注意:若已知a是char型变量,则a=′*′是合法的赋值表达式;a="*"则是非法的赋值表达式。因为C语言中没有字符串类型的变量,所以不能把一个字符串赋予一个字符变量。在C语言中通常用字符数组变量来存放字符串,这部分内容将在第7章中介绍。

(2)复合赋值运算符(+=、-=、*=、=、%=、&==、|=、>>=、<<=、^=)。

在“=”之前加上其他运算符,可以构成复合赋值运算符。C语言采用复合赋值运算符,一是为了简化程序,使程序精练;二是为了提高编译效率,产生质量较高的目标代码。

例如,下面的式子都是正确的赋值表达式:

注意:赋值的过程实际上是把值送到变量代表的存储单元,因此值运算符的左边必须是变量;右边则可以是变量、常量或表达式。例如,以下均是不合法的赋值表达式:

3.3.6 条件运算符及其表达式

C语言提供的条件运算符“?∶”的一般格式为:

运算规则为如果表达式1的值为非0(即逻辑真),则运算结果等于表达式2的值;否则等于表达式3的值。也就是说表达式2与表达式3中只有一个被执行,而不会全部执行。

例如,下面的式子都是正确的条件表达式:

说明:条件运算符是C语言中唯一的三目运算符,要求有3个操作对象。其中表达式1、表达式2和表达式3可以是任意合法的表达式,它们的类型可以各不相同。

当双分支选择结构中语句部分都较为简单时,可以用条件运算符来代替,使程序更为简练。

3.3.7 逗号运算符及其表达式

逗号运算符又称为“顺序求值运算符”,通过该运算符可以将多个表达式连接起来构成逗号表达式。逗号表达式的一般格式如下:

运算规则为先求表达式1的值,然后求表达式2的值。依此类推,直到求出最后一个表达式n的值,整个逗号表达式的值是最后一个表达式n的值。

例如,逗号表达式“m+7,2*a,7%2”的值为1。

通常情况下,使用逗号表达式不是为了取得和使用这个逗号表达式的最终结果值,而是为了分别按顺序求得每个表达式的结果值。

注意:并不是任何地方出现的逗号都是逗号运算符,很多情况下逗号仅用做分隔符。

例如,定义int a,b,c;中的逗号是分隔符,而不是逗号运算符。

3.3.8 求字节数运算符

sizeof 运算符是一个求字节数运算符,它是一个单目运算符,一般格式为:

功能为返回某数据类型、某变量或者某常量在内存中的字节长度。

例如,用sizeof求各数据类型,以及常量和变量的字节数: