您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > class03 运算符和表达式
面向对象程序设计与实践第3课运算符和表达式主讲人:杨峰Page1本课主要内容运算符运算符的优先级表达式表达式的求值顺序Page21表达式的概念1.1表达式的概念什么是表达式(expression)?表达式是程序的最基本构造块表达式由运算符和操作数组成,通过运算符对操作数的运算得到一个值最简单的表达式是字面量和变量名length=20;字面量20是一个表达式,它的值就是20length也是表达式赋值运算符=和2个操作数length,20组成一个赋值表达式,该表达式的值是20赋值表达式加一个;号,就是一条赋值语句Page31表达式的概念1.1表达式的概念简单表达式通过运算符组合构成更复杂的表达式intperimeter=(length+width)*2;算术表达式算术表达式赋值表达式赋值表达式末尾加分号,构成一个赋值语句。Page41表达式的概念1.2左值的概念一个对象在内存中占据一片连续的区域,左值就是指向某个对象的表达式。左值的概念比变量更广泛变量是有名的对象而左值则可以表示有名和无名的对象int*rs=newint(20);cout*rsendl;用new运算符在内存中分配了一个值为20的整型变量,这个变量就没有名字,只能通过指针的取内容运算*rs来操作这个变量,因此*rs是一个左值(无名对象)算术表达式1.0/r1就不是一个左值(表达式计算得到的值存放在CPU寄存器中,不是内存中的对象)这个名称的来历原意是说这样一个表达式可以出现在赋值运算符的左侧。但实际上并不是所有左值都能出现在赋值运算符的左侧,指向常量的左值就不能出现在赋值预算符的左侧。没有被声明为常量的左值称为可修改的左值(modifiablelvalue)才可以出现在赋值运算符的左侧。Page52常用运算符2.1sizeof运算符返回指定类型所占用的内存大小返回结果是一个无符号整型size_tintlen=sizeof(long);在32位系统中len得到的值为4,在64位系统中值为8严格一点,写成当然更好,但通常用int就可以了size_tlen=sizeof(long);Page62常用运算符2.2自增、自减运算符(后缀形式)lvalue++这个算术表达式的值是lvalue,然后再把lvalue的值加1intlvalue=10;intn=lvalue++;这2条语句执行以后,n的值为10,lvalue的值为11。Page72常用运算符这个运算符做了2件事,这种情况称为运算符的副作用这个运算符的副作用容易产生程序漏洞(我觉得(⊙o⊙)?不懂就算料~~)(C语言定义的这个运算符,优点是能方便地用于指针运算)intlvalue=10;intn=lvalue++;这2条语句执行以后,n的值为10,lvalue的值为11。Page82常用运算符2.2自增、自减运算符(前缀形式)++lvalue这个表达式将lvalue加1,表达式的值是lvalue+1。相当于lvalue=lvalue+1这个运算符做了2件事,也有副作用intlvalue=10;intn=++lvalue;这2条语句执行以后,n的值为11,lvalue的值为11。注意:自增、自减运算符只能对整型变量进行算术运算,不能用于浮点型变量。由于后缀形式的不一致性,所以建议尽量使用前缀形式Page92常用运算符2.2自增、自减运算符避免自增、自减运算符引起歧义对整数运算,不使用后缀形式;不在一条语句中对同一变量多次使用自增自减运算符Page102常用运算符2.3算术运算符算术运算符包括加,减,乘,除和求余只有整型数才能求余。注意四则运算结果是否会产生溢出和回绕。unsignedshortn=65534;n=n+2;计算结果是0,而不是65536。因为只能表示0~65535的值,65536就会回绕到0。选择变量类型时需要选择足够大的变量类型,比如这里应该用unsignedintPage112常用运算符2.3算术运算符算术运算符包括加,减,乘,除和求余浮点数的减法,注意避免出现2个相近数相减整数的除法结果只取整浮点数的除法,如果出现除0,0/0或无穷大除无穷大,结果都是NaNdoublevalue=5/2;输出是2,因为字面值是整型,所以计算结果是整型2,再转换成浮点型还是2,不会自己变成2.5Page122常用运算符2.4赋值运算符基本形式只有可修改的左值能出现在赋值运算符的左侧2.5复合赋值运算符基本形式lvalue=exprlvalueop=expr等价于lvalue=lvalueop(expr)intn1=2;intn2=3;intn3=4;n3*=n1+n2;等价于n3=n3*(n1+n2);Page133数据类型转换基本原则在2种情况下会发生变量数据类型转换不同类型的变量进行算术运算时产生隐式数据类型转换,转换原则是向上提升赋值运算中,若赋值运算符两侧数据类型不同,产生数据类型转换。类型转换为赋值运算符左侧的目标类型Page143数据类型转换3.1算术运算中的数据类型转换如果运算符的2侧操作数类型不同,编译器执行隐式数据类型转换,并总是转换为二者中内存空间大,表示精度高的类型。这个原则称为向上提升1/radius假设radius是浮点型,1是整型,所以先将1转换为浮点型,再与radius执行除运算,结果为浮点型。Page153数据类型转换3.1算术运算中的数据类型转换复杂表达式从左向右逐个进行类型转换计算球的体积4/3*PI*radius*radius*radius4和3都是整型,所以执行一个整型的除法,结果为整型值1;1和PI相乘,PI是浮点型,所以1转换为浮点型,再进行乘运算,结果为浮点型,后面的乘运算都是浮点型;所以计算结果错误,纠正方法:4.0/3*PI*radius*radius*radius4/3.0*PI*radius*radius*radius4.0/3.0*PI*radius*radius*radius(推荐)PI*radius*radius*radius*4/3Page163数据类型转换3.2赋值运算的数据类型转换赋值运算总是将运算符右侧的计算结果转换为左侧的目标类型,可以隐式转换,也可以显式转换intside=50;doublevolumn;volumn=side*side*side;//隐式类型转换volumn=(double)(side*side*side);//C的显式类型转换volumn=double(side*side*side);//C++的显式类型转换注意2种写法的差别:volumn=(double)(side*side*side);volumn=(double)side*side*side;Attention!~前一种执行3个整型的乘运算,结果是整型,显式转换为double型再赋值。后一种是将第一个操作数显式转换为double型,再执行2个浮点型乘运算,结果为浮点型,最后赋值。Page173数据类型转换3.2赋值运算的数据类型转换intstudents_num=35;intscore_total=2883;doublescore_avg=score_total/students_num;给定班级人数和总成绩,求平均成绩:doublescore_avg=(double)score_total/students_num;或者doublescore_total=2883;注意:如果右侧计算结果是占用空间比较大,精度更高的变量类型,而左侧是占用空间比较小,精度较低的类型时,赋值过程就会产生截断。截断会产生回绕,程序运行虽然不会马上崩溃,但是会造成隐藏的逻辑错误,在大软件中将很难查找这类错误。原则:尽量避免复合类型的数学运算和赋值运算提高程序可靠性。右侧是一个整型的除运算,得到的结果是整型值82。即使赋值执行了类型转换,得到的值也只是82.0,而不是正确的结果。这是很容易错的例子,应该对操作数执行一个类型转换:Page183数据类型转换3.3字面量的类型和运算中的类型转换longlongus=24*60*60*1000*1000;longms=24*60*60*1000;coutus/ms;举例:计算一天的微秒数:longlongus=24*60*60L*1000*1000;现在,右侧有一个long型,24×60计算结果是int型,×60L,因为60L是long型,所以计算提升为long型(即先将24×60的结果转换为long再和60L相乘,结果是long型),后面的计算都是long型。如果是64位系统,这个修改就可以得到正确的结果。但是32位系统中long和int是一样的(都是4个字节),只有大于4294967295的数加L才是longlong型,所以这个修改达不到效果。us是一天的微秒数,ms是一天的毫秒数,相除,显然结果应该是1000。但是编程试一试,我们得到的是5。因为右侧的数全是整型,所以计算结果是个整型,已经溢出了,然后再转换成longlong已经没有用了Page193数据类型转换3.3字面量的类型和运算中的类型转换longlonglms=24*60*60*1000;longlongus=1000*lms;longms=24*60*60*1000;coutus/ms;只好增加一个中间变量:先以整型计算,赋值转换成longlong型。1000×lms因为lms是longlong型,所以1000先转换成longlong型再和lms相乘就不会溢出,得出正确的结果1000。(这样的错误例子如果出现在一个大型的软件里面,就会很难发现)注意:选择变量类型时应先估计变量在实际实用中能达到的范围,从而选择合适的类型。字面量常常被忽略需要的后缀,产生类型错误Page203数据类型转换3.4显式数据类型转换显式类型转换有3种表达方法:C形式:Tlvalue=(T)expr;这里T代表左侧变量的数据类型(目标类型)函数型:Tlvalue=T(expr);cast型:Tlvalue=static_castT(expr);C用第1种。C++建议用第3种,如:volumn=static_castdouble(side*side*side);Page214运算符的优先级与结合性4.1运算符优先级运算符的优先级基本可以归结为:单目高于双目双目高于三目三目高于赋值从低到高:赋值——三目——双目——单目Page224运算符的优先级与结合性已经学过的运算符中sizeof运算符优先级高;自增、自减运算符优先级较高;四则运算符与数学规定相同,先乘除(求余),后加减然后是赋值运算符和复合赋值运算符。从低到高:赋值运算符和复合赋值运算符——四则运算符——自增、自减运算符——sizeof运算符括号可以改变运算优先级Page234运算符的优先级与结合性4.2运算符的结合性大部分的运算符都是从左往右计算的,这种方向称为结合性(这是一个小小的定义(⊙o⊙)哦~)算术运算符具有左结合性,比如intresult=m*n*u*v*w;从左向右计算赋值运算符是右结合的。((⊙o⊙)…这是个特例)比如Thirdvalue=SecondValue=FirstValue=expr;就是先执行FirstValue=expr,然后执行SecondValue=FirstValue,再执行Thirdvalue=SecondValue大部分单目运算符是右结合的,因为通常是单目运算符在前面,变量跟后面。比如-value,++value;后置的++和--是左结合,因为写出来是这个样子value++。即单目运算符总是和紧挨着它的那个变量结合到一块通常不用关心结合性的问题,运算符的结合性是完全符合习惯的Page244运算符的优先级与结合性4.2运算符的结合性a+++b是表示(a++)+b还是a+(++b)?因为编译器总是从左向右读入toke
本文标题:class03 运算符和表达式
链接地址:https://www.777doc.com/doc-3184515 .html