第 3章 运算符和表达式
3.1概述
3.2运算符及表达式简介
3.1概述
C语言的运算符非常丰富,使用方法也非常灵活,这是
C语言的主要特点。 C语言有 44个运算符,其中一部分与其他的高级语言相同,而另外一部分与汇编语言相似。
C语言的语句虽然高于硬件指令级,但有些运算符却和硬件指令级接近,基本上反映了计算机硬件的操作,能对特定的物理地址进行访问。所有这些特点使 C语言代替汇编语言成为可能。正是 C语言的众多运算符、优先级和结合性,给学过其他高级语言的程序编写人员带来了困扰。所以,突破 "先入为主 "的影响,使初学者尽快越过运算符和表达式这一关是非常重要的。
3.1.1 C语言运算符
3.1.1 C语言运算符
运算符必须有运算对象。 C语言中的运算符的运算对象如果是一个,称单目运算;运算对象是两个,称双目运算;也有运算对象是三个的,称三目运算。 C语言中对运算符级别有明确规定,称为运算符的 "优先级 "。同级运算符还规定了结合性,这种结合性是其它高级语言的运算符所没有的。若是从左向右结合称为 "左结合 ",从右向左结合称为 "右结合 "
3.1.2 C语言表达式
由常量、变量、函数和运算符组合起来的式子称为“表达式”,根据运算规则进行运算后得出来的结果称为
“表达式的值”。
运算符指出表达式中单个或多个操作数如何参与运算。
表达式计算所产生的值依赖于表达式中运算符的优先级及结合性。
①用圆括号括起来的表达式是初等表达式。任何操作数都可以包含在圆括号中,用圆括号括起来的表达式对数据类型和它的值没有影响。圆括号主要用于改变表达式计算的次序。
②使用方括号表示的数组元素的下标表达式是初等表达式,
例如 x[ 5],array[ i][ j]都是初等表达式。
③ 使用 "->"或 ","表示结构体或共用体成员的成员选择表达式是初等表达式,例如,p->a和 intem,b是两个初等表达式。。
④标识符、常量是初等表达式。例如,123,"TURBOC"、
string和 ARRA是四个初等表达式。
⑤左值表达式是初等表达式。所谓的左值表达式就是能表示存储单元的表达式。例如:
int x,a,b,C; x=a/b+c;
这是一个赋值表达式语句;又简称赋值语句,其中 x称为左值表达式,它指向一个可修改内容的存储单元,而
a/b+c是一算术表达式。
3.1.2 C语言表达式
3.2 运算符和表达式简介
3.2.1 算术运算符和算术表达式,
算术运算符用于各类数值运算,包括 +,-,*,/,%、
++,--七种,表 3-1列出了各种算术运算符 。
1.基本算术运算符基本算术运算包括:
+(单目取正),-(单目取负),+(加),-(减),*
(乘),/(除),%(取模)
基本算术运算符的优先级运算优先级规则
在基本算术运算符中,单目运算符的结合性为右结合,
双目运算的结合性为左结合。
C程序中,称表达式的运算结果为表达式的值。 C语言规定,在表达式求值时,须按运算符优先级的高低次序执行。对算术运算而言,必须遵循先括号内后括号外,
先乘、除及求余运算,后加减的运算优先级规则。
C语言中,运算符的运算优先级共分为 15级。 1级最高,
15级最低。在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。
2.自增自减运算符
自增运算符 (++)的功能是使变量的值自增 1,自减运算符 (--)的功能是使变量的值自减 1。自增、自减运算符只能用于变量,自增、自减运算符的优先级高于基本算术运算符,自增、自减运算符具有右结合性。
自增、自减有前缀和后缀两种形式:
++i变量自增 1后再参与运算;
i++变量参与运算后,i的值再自增 1;
--i变量自减 1后再参与运算;
i-- 变量参与运算后,i的值再自减 1。
所有的自增运算符 ++均可以相应地变成自减运算符 (--)。
++a表示先将变量 a的值增加 1,再使用变量 a,,b=++a”
相当于,a=a+1;b=a;”。
a++表示先使用变量 a的值,再将变量 a的值增加 1,
,b=a++”相当于,b=a,a=a+1;”。
当 ++,--运算符作为函数的参数时,要注间参数表达式的运算顺序是从右到左。
2.自增自减运算符
3.算术表达式
由算术运算符和括号将运算对象 (常量、变量、函数等 )
连接起来的式子,称为算术表达式。有了算术表达式,
在编程时我们就可以将数学算术式写成 C语言的算术表达式。
两个整数相除的结果仍为整数,舍去小数部分的值。例如,6/4与 6.0/4运算的结果值是不同的,6/4的值为整数
1,而 6.0/4的值为实型数 1.5。这是因为当其中一个操作数为实数时,则整数与实数运算的结果为 double型。
求余运算限定参与运算的两个操作数为整数。其中,运算符左侧的操作数为被除数,右侧的操作数为除数,运算的结果为整除后的余数,若两个操作数中有一个为负数,则余数的符号与编译程序的实现方法有关。
3.2.2 关系运算符和关系表达式
1.关系运算符关系运算符是逻辑运算中比较简单的一种。关系运算实质上是对两个操作数的数值或代码值进行比较运算。
2.关系表达式由关系运算符将两个表达式 (可以是算术表达式、关系表达式、逻辑表达式、赋值表达式或字符表达式等 )连接起来的式子称为关系表达式。
关系运算符的优先次序是:
①前四个运算符的优先级高于后两个运算符。
②关系运算符的优先级低于算术运算符。
③关系运算符的优先级高于位逻辑运算符和赋值运算符等
3.2.3 逻辑运算符和逻辑表达式
1.逻辑运算符逻辑 (Logic)运算也称为布尔 (Boolean)运算,c语言提供了 3种逻辑运算符!,& &,||
运算符!只需要一个操作数,故为单目运算符,而所有单目运算符的优先级都比其他运算符高,所以在这 3
个运算符中!的优先级是最高的,其次是 & &,再次是 ||。
2.逻辑表达式
用逻辑运算符连接操作数组成的表达式称为逻辑表达式。
其中的表达式主要为关系表达式,也可以是字符型数据和算术表达式、条件表达式、赋值表达式或逗号表达式等。逻辑表达式的值,或称逻辑运算的结果也只有真和假两个值。当逻辑运算的结果为真时,用 1作为表达式的值;当逻辑运算的结果为假时,用 0作为表达式的值。
逻辑运算符
( a)逻辑非运算符 ( b)逻辑与和逻辑或运算
a逻辑 逻辑非运算! a a b a&&b a‖ b
0 1 0 0 0 0
1 0 0 1 0 1
1 0 0 1
1 1 1 1
逻辑运算符
逻辑非!
逻辑非运算是对原值是否是非 0( ≠0)的判断,若 a的值为真,则 !a的值为假;若 a的值为假,则 !a的值为真
逻辑与 &&
逻辑与运算规则是,如果两个操作对象均为非 0时,则表达式的结果为 l,否则表达式的结果为 0。
逻辑或 ||
逻辑或运算规则是,两个操作对象中有一个为非 0值,
表达式结果就为 1。如果两个操作对象均为 0,表达式结果为 0
3.2.4 位运算符和位运算表达式
1.位运算符
在 C语言中,位操作运算主要是针对 int型和 char型数据类型而言,不适合用于 float型,double型、
long型和 void型等其他复杂类型位运算符 含义 优先级
| 或 低
∧ 异或
& 与
,左移 中
,右移
~ 接位取反 高位运算符
( 1)按位非运算按位非运算的规则是,将二进制的数字 0变 1,1变 0
( 2)按位与运算按位与运算的规则是:两个操作对象均为 1时,则该位结果为 1,
否则为 0
( 3)按位或运算按位或运算的规则是:两个操作对象有一个为 1时,则该位结果为 1,否则为 0。
( 4)按位异或运算符按位异或运算的规则是:两个操作对象相异时,则该位结果为 1,
相同时为 0
( 5)移位运算
C语言提供的移位运算实现将整型数据按二进位右移或左移的功能。向右移位的运算符为,">>",向左移位的运算符为,"<<"。
对位逻辑运算需注意以下四点:
① 位逻辑运算的操作数应该是整型数据。
②为了保证程序的可移植性,操作数应使用十进制、八进制或十六进制数的表示形式,而不要使用二进制数的表示形式。
③按位取反运算仅对操作数取反码,不能直接求其补码。
如果要求某操作数的补码,应先求其反码,再运用增 1
运算对反码加 1,使该操作数变为原操作数的补码。
④位逻辑运算与前面介绍的逻辑运算有质的区别。位逻辑运算是按位进行运算的,而逻辑运算是对整个数值按零和非零进行运算的。位逻辑运算要计算具体数值,而逻辑运算只判别表达式的值是 "真 "还是 "假 "。
3.2.5 赋值运算符和赋值表达式
1.赋值运算符
赋值运算符 (Assignment Operator)的含义是将一个数据赋给一个变量,书写形式与数学中的等号相同,但两者的含义是截然不同的。赋值运算符均为双目运算符。
赋值运算符运算符号名称 运算规则 参加运算的数据类型结果的数据类型
= 赋值 将右边表达式的值赋给左边的变量右边为表达式左边为变量整型、实型、字符型
+= 加赋值 x+=y= x=x+y 整型、实型、
字符型整型、实型、字符型
-= 减赋值 x-=y= x=x-y 整型、实型、
字符型整型、实型、字符型
*= 乘赋值 x*=y= x=x*y 整型、实型、
字符型整型、实型、字符型
/= 除赋值 x/=y= x=x/y 整型、实型、
字符型整型、实型、字符型
%= 模赋值 x%=y x=x%y 整型 整型
2.赋值表达式
由赋值运算符及相应操作数组成的表达式称为赋值表达式。赋值表达式的功能是计算表达式的值再赋予左边的变量。其一般形式为:
变量名 赋值运算符 表达式
C语言还允许下列赋值形式:
变量 1=变量 2=变量 3=…= 变量 n=表达式
这种形式称为多重赋值表达式,一般用于为多个变量赋予同一个值的场合。由于赋值运算符是右结合,因此执行时是把表达式值依次赋给变量 n,…,变量 1,即上面的形式等价于:
变量 1=(变量 2=(变量 3=(…=( 变量 n=表达式 )…)))
赋值表达式也有类型转换的问题
当赋值运算符两边的数据类型不相同时,系统将进行自动类型转换,即把赋值运算符右边的类型转换为左边的类型。转换规则如下:
实型( float,double)赋给整型变量时,只将整数部分赋给整型变量,舍去小数部分。
整型 (int,shor tint,long int)赋给实型变量时,数值不变,但将整型数据以浮点形式存放到实型类型变量中,
即增加小数部分 (小数部分的值为 0)。如 "float x,"执行
"x=6"后,先将 x的值 6转换为 6,000000,再存储到变量 x中。
赋值表达式也有类型转换的问题
字符型 (char)赋给整型 (int)变量时,由于字符型只占一个字节,整型为两个字节,所以 int变量的高八位补的数与 char的最高位相同,低八位为字符的 ASCII码值。如
"int x,x2=\154'; (01101100)",高八位补 0,
0000000001101100。同样 int赋给 long int,也按这个规则进行。
整型 (int)赋给字符型 (char),只把低八位赋给字符变量,
同样 long int赋给 int变量,只把低十六位赋给 int变量。
由此可见,当右边表达式的数据类型长度比左边的变量定义的长度要长时,将丢失一部分数据,这样会降低精度。
注意:
不能把赋值运算符看成数学中的等于号,二者在概念上完全不同。
格式中的表达式部分允许是一个赋值表达式,这样就构成了多重赋值。多重赋值表达式中,赋值运算符遵循右结合的法则,即:自右向左的运算顺序。
在进行赋值运算时,应当注意赋值运算符右边表达式运算结果的类型与被赋值的变量类型的一致性,以避免错误的结果。例如:定义 int a;
执行 a=10.0/4;由于 a是整型变量,所以最终 a的值是 2
而不是 2.5。
3.2.6 逗号运算符和逗号表达式
逗号表达式是由逗号运算符“,”与其它表达式组成的表达式,逗号表达的一般形式为:表达式 1,表达式 2;
逗号表达式的运算规则为:先计算表达式 1,再计算表达式 2,逗号表达式的最后结果为表达式 2的计算结果。
注意:
①逗号表达式有可能降低程序的可读性,不利于养成良好的编程习惯;建议大家在编写程序时,少用或不用逗号表达式。
②程序中使用逗号表达式,通常是要分别求逗号表达式内各表达式的值,并不一定要求整个逗号表达式的值。
③并不是在所有出现逗号的地方都组成逗号表达式,如在变量说明中,函数参数表中的逗号只是用做各变量之间的间隔符。
3.2.7 条件运算符和条件表达式
条件运算符由 '?'号和 ','号组成,是 C语言中仅有的一个三目运算符,该运算符需要三个操作数,它能够实现简单的选择功能,条件表达式的形式是:
表达式 1?表达式 2,表达式 3
其中,表达式 1必须是布尔型;表达式 2,表达式 3可以是任何类型,且类型可以不同。条件表达式的类型为表达式 2和表达式 3中类型高的一个类型。
条件表达式的执行顺序是:先求表达式 1的值,若表达式 1的值为非零时,整个条件表达式的值为表达式 2的值;
若表达式 1的值为零,则整个条件表达式的值为表达式 3
的值,
3.2.8其他运算符
sizeof运算符
sizeof运算符用于计算某种类型的运算对象在计算机中所占用的存储空间的字节数。长度运算符 sizeof是单目运算符,其运算的对象可以是数据类型符或变量。注意,
运算对象要用圆括号括住。
本章小结
本章主要介绍 C语言中的运算符和表达式的定义和使用规则,C语言中的运算符较多,需要注意的问题也多。
在算术运算符中自增 (++)和自减 (--)两个运算符在变量前后的位置不同,运算顺序也不同;在表达式中,各运算量参与运算的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的制约,以便确定是自左向右进行运算还是自右向左进行运算。因此,在学习本章内容的时候,要多联系、多总结,各种运算符对比记忆,
以达到事半功倍的效果。
常用运算符的优先级与结合性优先级顺序运算符种类 附加说明 结合方向
1 单目运算符 逻辑非!按位取反~ 求负 - ++ -- 类型强制转换等 右 → 左
2 算术运算符 * / % 高于 +- 左 → 右
3 关系运算符 除逻辑非之外,&&高于 左 → 右
4 逻辑运算符 < <= > >= 高于 == != 右 → 左
5 赋值运算符 ‖ = += -= *= /= %= &= ^= |= <<= >>= 右 → 左
6 逗号运算符 左 → 右