2020/1/291C语言程序设计第三章表达式与运算符2020/1/292内容提要表达式体现对数据的处理,由运算符和运算对象组成掌握每种运算符的以下知识:•对运算对象的要求•运算符的结合性•运算符的优先级•运算结果的特性有多种运算符的复杂表达式的计算顺序及计算结果数据类型的自动转换规则及强制转换的方法2020/1/293表达式的组成表达式实现对数据的处理,每个表达式都有唯一的值表达式由运算对象和运算符组成运算对象的种类:常量、变量、有返回值的函数调用、其它表达式例:2arand()(2+a)*rand()运算符:共34种,分为15个不同的优先级可以理解成是不带运算符的最简单表达式常量表达式变量表达式函数表达式带运算符的表达式2020/1/294左值与右值每个表达式都有唯一确定的值,表达式不是左值就是右值右值:只能出现在赋值号(=)右边的表达式左值:不是右值的表达式就是左值左值与右值的关系:右值只能出现在赋值号的右边;而左值既可以出现在赋值号的左边,又可以出现在赋值号的右边。左值可以取地址,右值不可以取地址.例:2arand()(2+a)*rand()a=b常量表达式只能作为右值例:a=2;(右值)变量表达式为左值,既可在赋值号左边也可以在右边,例:a=5;(左边)b=a;(右边)此函数表达式为右值例:a=rand()右值)此表达式只能作为右值例:b=(2+a)*rand();(右值)赋值表达式只能作为右值例:c=a=b;(右值)(a=b)=c;(出错)2020/1/295算术运算符算术运算符主要完成数值计算问题,具体如下表所列运算符优先级结合方向对运算对象的要求运算结果特性特殊说明-取负2从右到左整、实型值运算对象的相反数单目运算符++自增整,实,字符,指针型变量结果与变量的值可能一致单目,分为前++后++--自减单目,分为前--后--*乘3从左到右允许整型与实型数混合只要有1个实对象结果实型,否则整型结果/除两个整数相除只能得到整数商%取余仅限整型数整除的余数正负号同第1数+加4从左到右允许整型与实型数混合只要有1个实对象结果实型,否则整型结果-减例:inta=3,b,c;a++的表达式结果是3,变量a的值是4;++a的表达式结果是4,变量a的值是4;因此,c=a++执行后,c的值是3,a的值是4b=++a执行后,b的值是4,a的值也是4例:inta=3;-a结果为-3,但是变量a的值仍为3-2.45是2.45的相反数例:inta=3,b,c;a--的表达式结果是3,变量a的值是2;--a的表达式结果是2,变量a的值是2;因此,c=a--执行后,c的值是3,a的值是2b=--a执行后,b的值是2,a的值也是2例:inta=27,b=5,c;表达式a/b结果是5,而不是5.4表达式27.0/b结果是5.4表达式27.0/5.0结果是5.4例:inta=27,b=5,c;表达式a%b结果是2,表达式-a%b结果是-2表达式27.0%b是错误的例:表达式2+3结果是5表达式2+3.0结果是5.0表达式2.0+3.0结果是5.0例:表达式3-2结果是1表达式3.0-2结果是1.0表达式3.0-2.0结果是1.02020/1/296算术运算符程序3.1赋值表达式及算术运算符示例#includestdio.h#includestdlib.h//包含随机函数rand的声明intmain(){inta=5,b=6,c=7;printf(“%d\n”,rand());//显示随机数print(%d\n,a*(b+c)/2-2);//显示算术表达式的值printf(%d\n,a=b);//显示赋值表达式即a的值b=rand()%10;//混合表达式赋0至9之间的1个随机数printf(“%d\n”,c=a=b);//显示赋值表达式的值即c的值return0;}运行结果4130672020/1/297关系运算符关系运算符主要完成表达式间的比较,比较的结果非真即假,C语言中无逻辑类型,故用1表示真,0表示假任何类型的值,只要不等于0,在需要作出真假判断的场合就代表逻辑真。运算符优先级结合方向对运算对象的要求运算结果特性大于6从左到右允许不同类型的值混合计算,运算对象非0就表示真值,0表示假,当类型不一致时,会自动进行类型转换为同一种类型关系表达式的最终结果只有两个值:1或0,1表示真,0表示假用括号可以提升优先级,有时为了更清晰小于=大于等于=小于等于==相等7!=不相等结论:关系运算符的优先级低于算术运算符例:c(a+b)可以写成:ca+b例:(ab)!=c可以写成:ab!=c例:a==(bc)可以写成:a==bc例:(d=c)=(a+b)用括号表达式的含义清楚2020/1/298关系运算符程序3.2关系运算示例#includestdio.h#includestdlib.h//包含随机函数rand的声明intmain(){inta=rand()%10;//产生3个0~9的随机数intb=rand()%10;intc=rand()%10,d;printf(“a=%d,b=%d,c=%d\n”,a,b,c);//输出printf(%d\n,c(a+b));printf(%d\n,(d=c)=(a+b));return0;}运行结果a=1,b=7,c=410rand()函数产生一个非负随机整数,产生一个[a,b]范围的非负随机整数的方法是:a+rand()%(b-a+1)2020/1/299逻辑运算符逻辑运算符主要完成更复杂的条件判断逻辑表达式的最终结果只有两个:1表示真,0表示假。任何类型的值,只要不等于0,在需要作出真假判断的场合就代表逻辑真,0代表逻辑假运算符优先级结合方向对运算对象的要求运算结果特性说明!逻辑非2从右至左允许不同类型的值混合计算,运算对象非0就表示真值,0表示假一定是整型,并且只有两个值1和0,分别表示真和假单目运算符,置反运算对象真假&&逻辑与11从左至右两个对象都为真结果才为真||逻辑或12两个对象只要有1个真结果就为真★几种运算符的优先级:单目-算术-关系-逻辑与-逻辑或例:!‘A’结果为0,!(2+35)结果为1例:(ab)&&(xy)可以写成:ab&&xy例:(a==b)||(x==y)可以写成:a==b||x==y例:(!a)||(a!=b)可以写成:!a||a!=b例:表达字符变量ch是大写字母的正确条件为:ch=‘A’&&ch=‘Z’,而不是:‘A’=ch=‘Z’,例:表达整型变量y是闰年的正确条件为:y%400==0||y%4==0&&y%100!=02020/1/2910逻辑运算符逻辑与、逻辑或运算符具有短路功能——当第一运算对象的结果就是表达式结果时,第二运算对象不作计算逻辑运算符的真值表及短路说明如下表所示:a(第1运算对象)b(第2运算对象)!aa&&ba||b真真假真(两个对象都要计算)真(短路,不计算第2对象)真假假假(两个对象都要计算)真(短路,不计算第2对象)假真真假(断路,不计算第2对象)真(两个对象都要计算)假假真假(断路,不计算第2对象)假(两个对象都要计算)逻辑与短路总结:当第一对象的值为假时,第二对象无需计算。因为无论第二对象结果是什么,最终表达式的值肯定为假逻辑或短路总结:当第一对象的值为真时,第二对象无需计算。因为无论第二对象结果是什么,最终表达式的值肯定为真2020/1/2911逻辑运算符逻辑表达式结果说明(ab)&&(c=c*2)0,c的值仍为7短路,因为ab的结果为0,故c=c*2不执行(ab)&&(c=c*2)1,c的值为14不短路,因为ab的结果为1,故c=c*2执行(ab)&&(c=c-7)0,c的值为0不短路,因为ab的结果为1,故c=c-7执行(ab))||(c=c*5)1,c的值仍为7短路,因为ab的结果为1,故c=c*5不执行(ab)||(c=c*5)1,c的值为35不短路,因为ab的结果为0,故c=c*5执行(ab)||(c=c-7)0,c的值为0不短路,因为ab的结果为0,故c=c-7执行假设已有定义:inta=5,b=6,c=7;下表给出了&&和||的短路功能练习:设有语句:inta=3,b=5,m=0;则执行语句a+b8&&(m=a=3)后,m的值为____,整个表达式的值为_______2020/1/2912逻辑运算符程序3.3逻辑运算示例#includestdio.h#includestdlib.h//包含随机函数rand的声明intmain(){inta=1+rand()%50,b=1+rand()%50;intx=rand()/a,y=rand()/b;printf(%d,%d,%d\n,a,b,ab);printf(%d,%d,%d\n,x,y,xy);printf(%d\n,(ab)&&(xy));printf(%d\n,(a==b)||(x==y));printf(%d\n,(!a)||(a!=b));return0;}运行结果42,18,0150,1472,1001rand()函数产生一个非负随机整数,产生一个[a,b]范围的非负随机整数的方法是:a+rand()%(b-a+1)2020/1/2913自增自减运算符在算术运算符中已提到单目运算符自增(++)和自减(--)自增自减运算符的几个特殊性:•(1)这两种运算符专门用于改变一个变量自身的值(增或减1),因此实质上具有赋值功能,运算对象只能是一个变量。•(2)对变量变化的时机取决于运算符与运算对象的相对位置,有前后之分,++a和—a为前++(--),a++和a—为后++(--)•(3)前++或前—是指先改变变量的值,再用变化后的值参加运算;后++或后—是指先用未变化过的变量的值参加表达式的运算,最后再改变变量的值。共同点就是变量值肯定改变•(4)需要区分表达式的值和变量的值,大部分情况下不是一回事,但是如果仅仅改变变量而不用它运算,则前后无区别2020/1/2914自增自减运算符表达式等价表示表达式的值变量的值x=i++;x=i;i=i+1;2i=3x=++j;j=j+1;x=j;5j=5x=i--;x=i;i=i-1;2i=1x=--j;j=j-1;x=j;3j=3x=(i++)+(++j);j=j+1;x=i+j;i=i+1;7i=3,j=5x=(i--)+(--j);j=j-1;x=i+j;i=i-1;5i=1,j=3x=x+i++;x=x+i;i=i+1;10i=3x=x+++i;x=x++;x=x+i;11i=3++(++i);i=i+1;i=i+1;4i=4i++;或++i;i=i+1;3i=3假设已有定义:intx=8,i=2,j=4;下表列出了有自增自减运算符的表达式的值及变量的值2020/1/2915自增自减运算符程序3.4自增自减运算示例#includestdio.hintmain(){inti=5,j=6,k;i++;++j;//相当于i=i+1;j=j+1;printf(i=%d,j=%d\n,i,j);i--;--j;//相当于i=i-1;j=j-1;printf(i=%d,j=%d\n,i,j);k=(i++)+(++j);//相当于j=j+1;k=i+j;i=i+1;printf(i=%d,j=%d,k=%d\n,i,j,k);k=(i--)+(--j);//相当于j=j-1;k=i+j;i=i-1;printf(i=%d,j=%d,k=%d\n,i,j,k);return0;}运行结果i=6,j=7i=5,j=6i=6,j=7,k=12i=5,j=6,k=122020/1/2916位运算符位运算是对字节或字内的二进制数位进行测试、抽取、设置或移位等操作,是C语言可对硬件