版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1第4章表达式2表达式是表示如何计算值的公式。使用运算符将操作数连接起来构成公式。操作数可以是变量、常量和表达式。运算符是构成表达式的基本工具算术运算符:+、-、*、/关系运算符:、逻辑运算符:&、|地址运算符:& 表达式可以构成表达式语句,在C语言中有重要应用。什么是表达式 本章要点算术运算符赋值运算符自增和自减运算符表达式求值表达式语句4.1 算术运算符C提供5个二元算术运算符: + 加(addition) - 减(subtraction) * 乘(multiplication) / 除(division) % 取余(remainder)二元算术运算符需要两个操作数。两个一元算术运算符:+
2、 一元正号运算符- 一元负号运算符二元算术运算符二元算术运算符允许操作数为整数或浮点数,也可以是两者混合。当操作数为整数和浮点数混合,结果为浮点数。 9 + 2.5f 结果为 11.5 6.7f / 2 结果为 3.35/ 和 % 运算符当两个操作数是整数时,运算符/”会丢掉分数部分来获取结果。因此1/2的结果是 0而不是0.5。运算符%要求操作数是整数,任一个操作数不是整数,编译无法通过。把0做为右操作数,会导致未定义行为。当运算符/和 %用于负操作数,在C89中其行为由实现定义(implementation-defined),除法的结果可以是向上取整,也可以是向下取整。由实现定义的行为Im
3、plementation-Defined BehaviorC标准中故意对C语言的部分内容未加指定,其细节由“实现”(特定平台上的编译、链接和执行软件)来定义。这是为了保证C的高效性,意味着与硬件相匹配。!尽量避免编写依赖于实现定义行为的程序以确保可移植性。一元算术运算符一元算术运算符需要一个操作数:i = +1;j = -i;一元正号+运算符无任何操作,强调某个数值常量是正的经典C没有这个运算符。运算符的优先级算数运算符的优先级如下:最高优先级:+ - (一元) * / %最低优先级:+ - (二元) 例子: i + j * k 等价于 i + (j * k)、 -i * -j 等价于 (-i
4、) * (-j) +i + j / k 等价于 (+i) + (j / k)运算符的结合性当表达式包含两个或更多个相同优先级的运算符时,就需要运算符的结合性。运算符从左向右结合时,称为左结合性。二元运算符 (*, /, %, +, 和-)是左结合 i - j k 等价于 (i - j) k i * j / k 等价于 (i * j) / k、运算符从右向左结合时,称为右结合性。一元运算符 ( +和-)是右结合、 - + i 等价于 -(+i)例: 计算UPC校验位美国和加拿大的货物使用通用产品代码 UPC (Universal Product Code):第一个数字:表示种类。第一组五个数字:
5、标识生产厂商。第二组五个数字:标识产品最后一个数字:校验位校验位计算第1、3、5、7、9、11位的数字相加。第2、4、6、8、10位的数字相加。第一次加的结果乘3,和第二次加的结果相加。把结果减1,再除10取余数。最后用9减余数,得到校验位。例: 计算UPC校验位校验位计算:第一次的和:0 + 3 + 0 + 1 + 1 + 3 = 8第二次的和:1 + 8 + 0 + 5 + 7 = 21第三步:8*3+21=45第四步:(45-1)%10=4第五步:9-4=5例: 计算UPC校验位(upc.c)11位的UPC要求用户分三步录入:Enter the first (single) digit:
6、 0Enter first group of five digits: 13800Enter second group of five digits: 15173Check digit: 5程序不是按1个5位数来读取的,而是按照5个1位数读入的。使用scanf的 %1d 转换说明,只匹配1位整数。/* Computes a Universal Product Code check digit */#include int main(void) int d, i1, i2, i3, i4, i5, j1, j2, j3, j4, j5,first_sum, second_sum, total;
7、printf(Enter the first (single) digit: ); scanf(%1d, &d); printf(Enter first group of five digits: ); scanf(%1d%1d%1d%1d%1d, &i1, &i2, &i3, &i4, &i5); printf(Enter second group of five digits: ); scanf(%1d%1d%1d%1d%1d, &j1, &j2, &j3, &j4, &j5); first_sum = d + i2 + i4 + j1 + j3 + j5; second_sum = i1
8、 + i3 + i5 + j2 + j4; total = 3 * first_sum + second_sum; printf(Check digit: %dn, 9 - (total - 1) % 10); return 0; 4.2 赋值运算符简单赋值运算符= (Simple assignment)复合赋值运算符 (Compound assignment)4.2.1 简单赋值v = e,求表达式e的值,把此值赋给v.e可以是常量、变量或更复杂的表达式:i = 5; /* i is now 5 */j = i; /* j is now 5 */k = 10 * i + j; /* k is
9、 now 55 */v和e的类型不同,赋值运算符会把e的值转换成v的类型:int i; float f;i = 72.99f; /* i is now 72 */f = 136; /* f is now 136.0 */简单赋值在C语言中赋值是运算符。赋值操作产生结果,v = e就是赋值运算后 v的值。int i; i=72.99f; /* i的值是72,而不是72.99*/副作用(side effect )一个运算符如果修改了操作数的值,说明这种运算符有副作用( side effect )简单赋值运算符有副作用,它修改了左操作数。表达式 i = 0 把结果赋给了(副作用)。多个赋值运算符可以
10、串联在一起:i = j = k = 0;运算符 = 是右结合,所以上面的表达式等价于:i = (j = (k = 0);副作用赋值运算符串联在一起,可能产生非预期效果:int i;float f;f = i = 33.3f; /*33赋给i,33.0赋给f,结果不是 33.3 */嵌入式赋值,不便于程序的阅读,也是隐含错误的根源:i = 1;k = 1 + (j = i);printf(%d %d %dn, i, j, k); /* prints 1 1 2 */4.2.2 左值(Lvalues)赋值运算符要求它的左操作数必须是左值。左值表示存储在计算机内存中的对象,而不是常量或计算的结果。变
11、量是左值,表达式10或2 * i不是。下面的例子都是非法的:12 = i; /* WRONG */i + j = 0; /* WRONG */-i = j; /* WRONG */编译器会检测这种错误,给出错误消息 :“invalid lvalue in assignment.”4.2.3 复合赋值利用变量原值计算新值并又赋给该变量:i = i + 2;C语言使用 += 复合赋值简化这种写法:i += 2; /* same as i = i + 2; */复合运算符-=,*=,/=,%= (其他的参见20章)i -= 2; /* same as i = i - 2; */i *= 2; /*
12、same as i = i * 2; */i /= 2; /* same as i = i / 2; */i %= 2; /* same as i = i % 2; */复合赋值i *= j + ki = i * j + k还是i = i * (j + k)?复合赋值i =+ j和 i += j是否一样?=+不是复合赋值符, i =+ j等价于i=(+j)复合赋值复合赋值运算符和=一样是右结合i += j +=k 相当于i += (j +=k) 4.3 自增和自减运算符自增(加1)和自减(减1):i = i + 1;j = j - 1;用复合运算符可以简化为:i += 1;j -= 1;C提供
13、了更简化的 +(自增)和-(自减)运算符+和- -运算符可以作为前缀(+i和-i)使用,也可以作为后缀使用( i+和i-)自增和自减运算符前缀会自增和自减变量本身:i = 1;printf(i is %dn, +i); /* i is 2 */printf(i is %dn, i); /* i is 2 */i = 1;printf(i is %dn, -i); /* i is 0 */printf(i is %dn, i); /* i is 0 */后缀是变量先不变,但随后自增和自减该变量:i = 1;printf(i is %dn, i+); /* i is 1 */printf(i is
14、 %dn, i); /* i is 2 */i = 1;printf(i is %dn, i-); /* i is 1 */printf(i is %dn, i); /* i is 0 */自增和自减运算符同一个表达式中多次使用 + 或 结果难理解: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。!尽量不使用这种难于理解的书写方式!4.4 表达式求值优先级名称符号结合性1(后缀)自增+左结合(后缀)自减-2(前缀)自增+右结合(前缀)自减-一元正号+一元负号-3乘法类* / %左结合4
15、加法类+ -左结合5赋值= *= /= %= += -=右结合表达式求值(P43)例子: 优先级a = b += c+ - d + -e / -fa = b += (c+) - d + -e / -f 1a = 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 子表达式的求值顺序有了运算符的优先级和结合性规则,可以把复杂表达式分解为子表达式。C语言没有定义表达式的求值顺序(除了含有
16、逻辑与和逻辑或运算符、条件运算符、逗号运算符的子表达式)。表达式 (a + b) * (c - d)无法确定 (a + b)是否在 (c - d)之前求值。无论表达式的计算顺序如何,大多数表达式的值是相同的。30子表达式的求值顺序当子表达式改变了某个操作数的值时,产生的值可能不一致:a = 5;c = (b = a + 2) - (a = 1);先执行b=a+2,则b的值为7,C的值为6。先执行a=1,则b的值为3,C的值为2。语句2的执行效果未定义。对这种情况,有些编译器会产生“operation on a may be undefined” 的警告信息。子表达式的求值顺序为了避免此类问题,不在子表达式中使用赋值运算符,而是采用分离的赋值表达式:a = 5;b = a + 2;a = 1;c = b - a;33自增自减也可以改变操作数:i = 2;j = i * i+;结果未定义,可能是4或6:1)取出第二个i,再自增;2)取出第一个i(新值);3)i的原始值和新值相乘,结果为6。子表达式的求值顺序未定义行为未定义行为(undefined behavior),和前面的由实现定义的行为不同。其后果是严重的:不同的编译器给出的编译结果不同。程序可能无法编译。或编译了无法运行,运行了可能崩溃,不
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 病房管理的分析与整改
- 【八年级】八年级英语上册odule-1-How-to-learn-English测试题(含答案)
- 子宫腺肌症产后护理
- 园林规划论文答辩
- 爱国教育进乡村国庆共筑乡村梦
- 寒假消防安全教育活动情况总结
- 怎样写护理论文
- 《主板总线插槽》课件
- 研究生复试时间管理
- 律师聘请合同格式模板示例
- 《出塞》优秀课件
- 末位淘汰制度
- 食堂组织架构图
- 三年级上册数学课件-7.3 同分母分数加减法丨苏教版 (共17张PPT)
- 工程地质实验报告
- 天猫电商客服部工作流程图
- 乙肝知识调查问卷调查
- 表面工程课程设计98405
- 幼儿园绘本故事:《小牛的春天》
- 铁路线路工起道作业指导书
- (完整版)股份代持协议英文模板0001
评论
0/150
提交评论