《ch表达式实用实用教案》由会员分享,可在线阅读,更多相关《ch表达式实用实用教案(33页珍藏版)》请在金锄头文库上搜索。
1、第4章: 表达式l 本章(bn zhn)要点n n算术算术(sunsh)(sunsh)运算符运算符n n赋值运算符赋值运算符n n自增和自减运算符自增和自减运算符n n表达式求值表达式求值n n表达式语句表达式语句第1页/共32页第一页,共33页。第4章: 表达式4.1算术算术(sunsh)运算符运算符C提供5个二元算术运算符:+加(addition)-减(subtraction)*乘(multiplication)/除(division)%取余(remainder)二元算术运算符需要两个操作数。两个一元(yyun)算术运算符:+一元(yyun)正号运算符-一元(yyun)负号运算符第2页/共
2、32页第二页,共33页。第4章: 表达式一元一元(yyun)算术运算符算术运算符一元算术运算符需要一个操作(cozu)数:i=+1;j=-i;一元正号+运算符无任何操作(cozu),强调某个数值常量是正的,经典C没有这个运算符。第3页/共32页第三页,共33页。第4章: 表达式二元算术二元算术(sunsh)运算符运算符i % j的值是i除j的余数. 10 % 3 的值为1 12 % 4 的值为0二元算术(sunsh)运算符允许操作数为整数或浮点数,也可以是两者混合。当操作数为整数和浮点数混合,结果为浮点数。 9 + 2.5f 结果为 11.5 6.7f / 2 结果为 3.35第4页/共32页
3、第四页,共33页。第4章: 表达式/和和%运算符运算符当两个操作数是整数时,运算符/”会丢掉分数部分来获取(huq)结果。因此1/2的结果是0而不是0.5。运算符%要求操作数是整数,任一个操作数不是整数,编译无法通过。把0做为右操作数,会导致未定义行为。当运算符/和%用于负操作数,在C89中其行为由实现定义(implementation-defined),除法的结果可以是向上取整,也可以是向下取整。在C99中,/的结果是向零截取的。第5页/共32页第五页,共33页。第4章: 表达式由实现由实现(shxin)定义的行为定义的行为Implementation-DefinedBehaviorC标准中
4、故意对C语言的部分内容未加指定,其细节由“实现”(特定平台上的编译、链接和执行软件)来定义。这是为了(wile)保证C的高效性,意味着与硬件相匹配。尽量避免编写依赖于实现定义行为的程序。第6页/共32页第六页,共33页。第4章: 表达式运算符的优先级运算符的优先级算数运算符的优先级如下(rxi):最高优先级:+-(一元)*/%最低优先级:+-(二元)例子:i+j*k等价于i+( j*k)、-i*-j等价于(-i)*(-j)+i+j/k等价于(+i)+( j/k)第7页/共32页第七页,共33页。第4章: 表达式运算符的结合运算符的结合(jih)性性当表达式包含两个或更多个(du)相同优先级的运
5、算符时,就需要运算符的结合性。运算符从左向右结合时,称为左结合性。二元运算符(*,/,%,+,和-)是左结合i-jk等价于(i-j)ki*j/k等价于(i*j)/k、运算符从右向左结合时,称为右结合性。一元运算符(+和-)是右结合、-+i等价于-(+i)第8页/共32页第八页,共33页。第4章: 表达式例子例子(lzi):计算计算UPC校验位校验位美国和加拿大的货物使用通用产品代码UPC(UniversalProductCode):第一个数字(shz):表示种类。第一组五个数字(shz):标识生产厂商。第二组五个数字(shz):标识产品最后一个数字(shz):校验位校验位计算第1、3、5、7、
6、9、11位的数字(shz)相加。第2、4、6、8、10位的数字(shz)相加。第一次加的结果乘3,和第二次加的结果相加。把结果减1,再除10取余数。最后用9减余数,得到校验位。第9页/共32页第九页,共33页。第4章: 表达式例子例子(lzi):计算计算UPC校验位校验位校验位计算(jsun):第一次的和:0+3+0+1+1+3=8第二次的和:1+8+0+5+7=21第三步:8*3+21=45第四步:(45-1)%10=4第五步:9-4=5第10页/共32页第十页,共33页。第4章: 表达式例子例子(lzi):计算计算UPC校验位(校验位(upc.c)11位的UPC要求用户分三步录入:Ente
7、rthefirst(single)digit:0Enterfirstgroupoffivedigits:13800Entersecondgroupoffivedigits:15173Checkdigit:5程序不是按1个5位数来读取的,而是按照5个1位数读入的。我们使用scanf的%1d转换说明(shumng),只匹配1位整数。第11页/共32页第十一页,共33页。第4章: 表达式/*ComputesaUniversalProductCodecheckdigit*/#includeintmain(void)intd,i1,i2,i3,i4,i5,j1,j2,j3,j4,j5,first_sum
8、,second_sum,total;printf(Enterthefirst(single)digit:);scanf(%1d,&d);printf(Enterfirstgroupoffivedigits:);scanf(%1d%1d%1d%1d%1d,&i1,&i2,&i3,&i4,&i5);printf(Entersecondgroupoffivedigits:);scanf(%1d%1d%1d%1d%1d,&j1,&j2,&j3,&j4,&j5);first_sum=d+i2+i4+j1+j3+j5;second_sum=i1+i3+i5+j2+j4;total=3*first_sum+
9、second_sum;printf(Checkdigit:%dn,9-(total-1)%10);return0;第12页/共32页第十二页,共33页。第4章: 表达式4.2赋值运算符赋值运算符简单( jindn)赋值运算符=(Simpleassignment)复合赋值运算符(Compoundassignment)第13页/共32页第十三页,共33页。第4章: 表达式4.2.1简单简单(jindn)赋值赋值v=e,求表达式e的值,把此值赋给v.e可以是常量、变量或更复杂(fz)的表达式:i=5;/*iisnow5*/j=i;/*jisnow5*/k=10*i+j;/*kisnow55*/v和e
10、的类型不同,赋值运算符会把e的值转换成v的类型:inti;floatf;i=72.99f;/*iisnow72*/f=136;/*fisnow136.0*/第14页/共32页第十四页,共33页。第4章: 表达式简单简单(jindn)赋值赋值在很多编程语言中,赋值是语句;然而(rnr)在C语言中赋值和+一样是运算符。赋值操作产生结果,v=e就是赋值运算后v的值。inti;i=72.99f;/*i的值是72,而不是72.99*/第15页/共32页第十五页,共33页。第4章: 表达式副作用(副作用(sideeffect)一个运算符如果修改了操作数的值,说明这种运算符有副作用(sideeffect)简
11、单赋值运算符有副作用,它修改了左操作数。表达式i=0把结果赋给了(副作用)。多个(du)赋值运算符可以串联在一起:i=j=k=0;运算符=是右结合,所以上面的表达式等价于:i=(j=(k=0);第16页/共32页第十六页,共33页。第4章: 表达式副作用副作用赋值运算符串联在一起,可能产生(chnshng)非预期效果:inti;floatf;f=i=33.3f;/*33赋给i,33.0赋给f,结果不是33.3*/嵌入式赋值,不便于程序的阅读,也是隐含错误的根源:i=1;k=1+(j=i);printf(%d%d%dn,i,j,k);/*prints112*/第17页/共32页第十七页,共33页
12、。第4章: 表达式4.2.2左值(左值(Lvalues)赋值运算符要求它的左操作数必须是左值。左值表示存储在计算机内存中的对象,而不是常量或计算的结果( jigu)。变量是左值,表达式10或2*i不是。下面的例子都是非法的:12=i;/*WRONG*/i+j=0;/*WRONG*/-i=j;/*WRONG*/编译器会检测这种错误,给出错误消息:“invalidlvalueinassignment.”第18页/共32页第十八页,共33页。第4章: 表达式4.2.3复合复合(fh)赋值赋值利用变量原值计算新值并又赋给该变量:i=i+2;C语言使用(shyng)+=复合赋值简化这种写法:i+=2;/
13、*sameasi=i+2;*/复合运算符-=,*=,/=,%/(其他的参见20章)i-=2;/*sameasi=i-2;*/i*=2;/*sameasi=i*2;*/i/=2;/*sameasi=i/2;*/i%=2;/*sameasi=i%2;*/第19页/共32页第十九页,共33页。第4章: 表达式复合复合(fh)赋值赋值i*=j+k不等于i=i*j+k,相当于i=i*(j+k)。注意(zhy):i=+j相当于i=(+j),和i+=j完全不一样复合赋值运算符和=一样是右结合i+=j+=k相当于i+=(j+=k)第20页/共32页第二十页,共33页。第4章: 表达式4.3自增和自减运算符自增
14、和自减运算符自增(加1)和自减(减1):i=i+1;j=j-1;用复合运算符可以简化为:i+=1;j-=1;C提供(tgng)了更简化的+(自增)和-(自减)运算符+和-运算符可以作为前缀(+i和-i)使用,也可以作为后缀使用(i+和i-)第21页/共32页第二十一页,共33页。第4章: 表达式自增和自减运算符自增和自减运算符前缀会自增和自减变量本身(bnshn):i=1;printf(iis%dn,+i);/*iis2*/printf(iis%dn,i);/*iis2*/i=1;printf(iis%dn,-i);/*iis0*/printf(iis%dn,i);/*iis0*/后缀是变量先
15、不变,但随后自增和自减该变量:i=1;printf(iis%dn,i+);/*iis1*/printf(iis%dn,i);/*iis2*/i=1;printf(iis%dn,i-);/*iis1*/printf(iis%dn,i);/*iis0*/第22页/共32页第二十二页,共33页。第4章: 表达式自增和自减运算符自增和自减运算符同一个表达式中多次使用+或结果难理解(lji):i=1;j=2;k=+i+j+;i,j,k的值为2,3,4。例子:i=1;j=2;k=i+j+;i,j,k的值为2,3,3。第23页/共32页第二十三页,共33页。第4章: 表达式4.4表达式求值表达式求值优先级名
16、称符号结合性1(后缀)自增+左结合(后缀)自减-2(前缀)自增+右结合(前缀)自减-一元正号+一元负号-3乘法类* / %左结合4加法类+ -左结合5赋值= *= /= %= += -=右结合第24页/共32页第二十四页,共33页。第4章: 表达式表达式求值(表达式求值(P43)例子(lzi):优先级a=b+=c+-d+-e/-fa=b+=(c+)-d+-e/-f1a=b+=(c+)-d+(-e)/(-f)2a=b+=(c+)-d+(-e)/(-f)3a=b+=(c+)-d)+(-e)/(-f)4(a=(b+=(c+)-d)+(-e)/(-f)5第25页/共32页第二十五页,共33页。第4章:
17、 表达式子表达式的求值顺序子表达式的求值顺序(shnx)有了运算符的优先级和结合性规则我们(wmen)可以把复杂表达式分解为子表达式。C语言没有定义表达式的求值顺序(除了含有逻辑与和逻辑或运算符、条件运算符、逗号运算符的子表达式)。表达式(a+b)*(c-d)无法确定(a+b)是否在(c-d)之前求值。Copyright 2008 W. W. Norton & Company.All rights reserved.26第26页/共32页第二十六页,共33页。第4章: 表达式子表达式的求值顺序子表达式的求值顺序(shnx)无论表达式的计算顺序如何,大多数表达式的值是相同的。但当子表达式改变了某
18、个(mu)操作数的值时,产生的值可能不一致:a=5;c=(b=a+2)-(a=1);先执行b=a+2,则b的值为7,C的值为6。先执行a=1,则b的值为3,C的值为2。语句2的执行效果未定义。对这种情况,有些编译器会产生“operationonamaybeundefined”的警告信息。第27页/共32页第二十七页,共33页。第4章: 表达式子表达式的求值顺序子表达式的求值顺序(shnx)为了避免此类问题,不在子表达式中使用赋值运算符,而是采用(ciyng)分离的赋值表达式:a=5;b=a+2;a=1;c=b-a;自增自减也可以改变操作数:i=2;j=i*i+;结果未定义,可能是4或6:1)取
19、出第二个i,再自增;2)取出第一个i(新值);3)i的原始值和新值相乘,结果为6。第28页/共32页第二十八页,共33页。第4章: 表达式未定义行为未定义行为(xngwi)未定义(dngy)行为(undefinedbehavior),和前面讲的由实现定义(dngy)的行为不同。其后果是严重的:不同的编译器给出的编译结果不同。程序可能无法编译。或编译了无法运行,运行了可能崩溃,不稳定或产生无意义结果。应该避免未定义(dngy)行为。第29页/共32页第二十九页,共33页。第4章: 表达式4.5表达式语句表达式语句(yj)C语言规定任何表达式都可以用作语句(加分号)+i;i自增,然后把新值取出,但
20、+i会被丢掉。因为(ynwi)会丢掉新值,除非有副作用,否则表达式用作语句就没有意义:i=1;/*useful*/i-;/*useful*/i*j-1;/*notuseful*/Copyright 2008 W. W. Norton & Company.All rights reserved.30第30页/共32页第三十页,共33页。第4章: 表达式表达式语句表达式语句(yj)键盘上的误操作容易造成“什么也不做”表达式:比如(br)输入:i=j;误输入为:i+j;某些编译器会检查无意义表达式,显示“statementwithnoeffect.” 警告。第31页/共32页第三十一页,共33页。C
21、opyright2008W.W.Norton&Company.Allrightsreserved.32感谢您的欣赏(xnshng)!第32页/共32页第三十二页,共33页。内容(nirng)总结本章要点。i = (j = (k = 0)。i *= j + k不等于 i = i * j + k,相当于i = i * (j + k)。注意:i =+ j相当于i = (+j),和 i += j完全不一样(yyng)。i += j +=k 相当于i += (j +=k)。+和- -运算符可以作为前缀(+i和-i)使用,也可以作为后缀使用( i+和i-)。= *= /= %= += -=第三十三页,共33页。