C语言中的算术运算符和算术表达式
C语言中运算和表达式的数量很多,C语言正是因为丰富的运算符和表达式使其语言功能十分完善。C语言的运算符不仅具有不同的优先级,还有结核性。在表达式中,各运算表达量参与运算的先后要遵守运算符优先级别的规定,也要受运算符结合姓的制约,以便确定是自左向右还是自右向左进行运算。这种结合性,增加了C语言的复杂性。
一、C语言运算符简介
C语言的运算符可以分为以下几类:
1.算术运算符:用于各类数值运算。包括加(+)、减(-)、乘(*)、除(/)、求余(%)、自增(++),自减(--),一共种;
2.关系运算符:用于比较运算。包括大于(>)、小于(<)、等于(==)、大于等于(>=)、小于等于(<=)、不等于(!=),一共6种;
3.逻辑运算符:用于逻辑运算。包括逻辑与(&&)、逻辑或(||),非(!),共3种。
4.位操作运算符:参与运算的量,按二进制位进行运算。包括位与(&)、位或(|)、位非(!)、位异或(^)、左移(<<)、右移(>>),共6种。
5.赋值运算符:用于赋值运算,分为简单赋值(=)、复合算术赋值(+=、-=,*=、/=、%=)、和复合位运算赋值(&=、!=、^=、>>=、<<=),三类共11种;
6.条件运算符:这是一个三目运算符,用于条件求值(? :);
7.逗号运算符:用于把若干表达式组合成一个表达式(,);
8.指针运算符:用于取内容(*)和区地址(&),两种运算;
9.求字节数运算符:用于计算数据类型所占的字节数(sizeof);
10.特殊运算符:有括号( )、下标[ ]、成员(->,)等几种。
二、算术运算符和算术表达式
1.基本的算术运算符
加法运算符“+”:加法运算符为双目运算符,即应有两个量参与加法运算。如a+b,1+2等,具有右结合性。
减法运算符“-”:减法运算符为双目运算符。但“-”也可作负值运算符,此时为单目运算,如-a,-1等,具有左结合性。
乘法运算符“*”:双目运算,具有左结合性。
除法运算符“/”:双目运算,具有左结合性。参与运算量均为整型时,结果也为整型,舍去小数。如果运算量中有一个是实型,则结果为双精度实型。
求余运算符(模运算符)“%”:双目运算,具有左结合性。要求参与运算的量均为整型。 求余运算的结果等于两数相除后的余数。
2.算术表达式和运算符的优先级和结合性
表达式是由常量、变量、函数和运算符组合起来的式子。一个表达式有一个值及其类型, 它们等于计算表达式所得结果的值和类型。表达式求值按运算符的优先级和结合性规定的顺序进行。
算术表达式:用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子。
运算符的优先级:C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。
运算符的结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式a-b+c则b应先与“-”号结合,执行a-b运算,然后再执行+c的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。最典型的右结合性运算符是赋值运算符。如a=b=c,由于“=”的右结合性,应先执行b=c再执行a=(b=c)运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。
3.强制类型转换运算符
其一般形式为: (类型说明符) (表达式)
其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。
例如:
(float)a 把a转换为实型
(int)(a+b) 把a+b的结果转换为整型
4.自增、自减运算符
自增1,自减1运算符:自增1运算符记为“++”,其功能是使变量的值自增1。自减1运算符记为“--”,其功能是使变量值自减1。
自增1,自减1运算符均为单目运算,都具有右结合性。可有以下几种形式:
++i i自增1后再参与其它运算;
--i i自减1后再参与其它运算;
i++ i参与运算后,i的值再自增1;
i-- i参与运算后,i的值再自减1。
在理解和使用上容易出错的是i++和i--。 特别是当它们出在较复杂的表达式或语句中时,常常难于弄清,因此应仔细分析。
举例:
main(){
int i=4;
printf("%d\n",++i);
printf("%d\n",--i);
printf("%d\n",i++);
printf("%d\n",i--);
printf("%d\n",-i++);
printf("%d\n",-i--);
}
i的初值为4,第2行i加1后输出故为5;第3行减1后输出故为4;第4行输出i为4之后再加1(为5);第5行输出i为5之后再减1(为4) ;第6行输出-4之后再加1(为5),第7行输出-5之后再减1(为4)。
举例:
main(){
int i=1,j=2,a,b;
a=(i++)+(i++)+(i++);
b=(++j)+(++j)+(++j);
printf("%d,%d,%d,%d",a,b,i,j);
}
这个程序中,对a=(i++)+(i++)+(i++)应理解为三个i相加,分别是1+2+3,故a值为6。然后i再自增1一次相当于加3故1的最后值为4。而对于b 的值则不然,b=(++j)+(++j)+(++j)应理解为j先自增1,再参与运算,3+4+5的和为12,j的最后值为5,b的值为12。
5.赋值运算符和赋值表达式
5.1赋值运算符
简单赋值运算符记为=。由=组建的式子称为赋值表达式。
简单赋值表达式格式:变量=表达式;
赋值表达式的作用就是将赋值号右边表达式的值赋给赋值号左边的对象。赋值表达式的类型为赋值号左边对象的类型,其结果值为赋值号左边对象被赋值后的值。
简单赋值表达式使用说明
赋值运算符的功能具有单向性,即只能将表达式的值传送变量,反之则不然。
赋值运算符左边只能是单个变量名,不能是其他运算量。
赋值运算符右边可以是常量、变量、函数或表达式。
④ 赋值运算符兼有计算与赋值双重功能,它首先计算出赋值运算符右边表达式的值,然后把此值再赋给左侧的变量。
⑤ 赋值运算符具有右结合性。因此a=b=c=5可理解为a=(b=(c=5)),即表达式值为5,a,b,c均为5。这个表达式从右向左运算,在c被更新为5后,表达式c=5的值为5,接着b的值被更新为5,最后a被赋值为5。
⑥ 凡是表达式可以出现的地方均可出现赋值表达式。例如,式子x=(a=5)+(b=8)是合法的。其意义是把5赋给a,8赋给b,再把a与b相加,和赋给x,故x应等于13。
⑦ 赋值运算符的优先级低于算术运算符。
⑧ 按照C++语言规定,任何表达式在其末尾加上分号就构成语句,所以在赋值表达式末尾加分号就构成了赋值语句,在程序中大量使用。
赋值运算中的自动类型转换
如果赋值运算符两边的数据类型不相同,系统将自动进行类型转换,即把赋值运算符右边的类型转换成左边的类型。具体规定如下。
(1) 实型赋给整型,舍去小数部分。
(2) 整型赋给实型,数值不变,但将以浮点形式存放,即增加小数部分(小数部分的值为0)。
(3) 字符型赋给整型,由于字符型为一个字节,故将字符的ASCII码值放到整型量的低八位中,高位为0。整型赋给字符型,只把低八位赋给字符量。
(4) 在赋值运算中,赋值运算符两边量的数据类型不同时,赋值运算符右边量的类型将转换为左边量的类型。如果右边量的数据类型长度比左边长,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。
三、逗号运算符和逗号表达式
C语言提供一种特殊的运算符——逗号运算符。用它将两个表达式连接起来。如:
3+5,6+8
称为逗号表达式,又称为“顺序求值运算符”。逗号表达式的一般形式为
表达式1,表达式2
逗号表达式的求解过程是:先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值。例如,上面的逗号表达式“3+5,6+8”的值为14。又如,逗号表达式
a=3*5,a*4
对此表达式的求解,读者可能会有两种不同的理解:一种认为“3*5,a*4” 是一个逗号表达式,先求出此逗号表达式的值, 如果a的原值为3,则逗号表达式的值为12,将12赋给a, 因此最后a的值为12。另一种认为:“a=3*5”是一个赋值表达式,“a*4”是另一个表达式,二者用逗号相连,构成一个逗号表达式。这两者哪一个对呢?赋值运算符的优先级别高于逗号运算符, 因此应先求解a=3*5(也就是把“a=3*5”作为一个表达式)。经计算和赋值后得到a的值为15,然后求解a*4,得60。整个逗号表达式的值为60。
一个逗号表达式又可以与另一个表达式组成一个新的逗号表达式,如(a=3*5,a*4),a+5 先计算出a的值等于15,再进行a*4的运算得60(但a值未变,仍为15),再进行a+5得20,即整个表达式的值为20。
逗号表达式的一般形式可以扩展为
表达式1,表达式2,表达式3……表达式n
它的值为表达式n的值。
逗号运算符是所有运算符中级别最低的。因此,下面两个表达式的作用是不同的:
① x=(a=3,6*3)
② x=a=3,6*a
第①个是一个赋值表达式,将一个逗号表达式的值赋给x,x的值等于18。
第②个是逗号表达式,它包括一个赋值表达式和一个算术表达式,x的值为3。
其实,逗号表达式无非是把若干个表达式“串联”起来。在许多情况下,使用逗号表达式的目的只是想分别得到各个表达式的值,而并非一定需要得到和使用整个逗号表达式的值,逗号表达式最常用于循环语句(for语句)中。
请注意并不是任何地方出现的逗号都是作为逗号运算符。例如函数参数也是用逗号来间隔的。如:
printf("%d,%d,%d",a,b,c);
上一行中的“a,b,c”并不是一个逗号表达式,它是printf函数的3个参数,参数间用逗号间隔。
如果改写为
printf("%d,%d,%d",(a,b,c),b,c);
则 (a,b,c)是一个逗号表达式,它的值等于c的值。括弧内的逗号不是参数间的分隔符而是逗号运算符。括弧中的内容是一个整体,作为printf函数的一个参数。
C语言表达能力强,其中一个重要方面就在于它的表达式类型丰富,运算符功能强,因而c使用灵活,适应性强。
总结:
1 、 左移运算符左移一位相当于乘二,其效率比乘以2的效率高。左移其右边自动补零,右移其左边补符号位。
2 、 这些操作符的优先级顺序 ! > 算术运算符 > 关系运算符 > && > || > 赋值运算符。
https://blog.csdn.net/sardine_c/article/details/49563661