下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C/C+运算符的优先级和结合性内容导读:遍历了 15个级别之后,让我们再来总结一下。其中我们可以看出这样两个规律:规律一、按照操作数个数来区分, 一元运算符高于二元运算符, 二元运算符高于三元运算符: 规律二、按照运算符的作用来区分,级别最高的是那些不是严格意义上的运算符, 次之是算 术运算.遍历了 15个级别之后,让我们再来总结一下。其中我们可以看出这样两个规律:规律一、按照操作数个数来区分,一元运算符高于二元运算符,二元运算符高于三元运 算符;规律二、按照运算符的作用来区分,级别最高的是那些不是严格意义上的运算符,次之是算术运算符,位移运算符,关系运算符,位运算符,逻辑运算符,赋值运算符。
2、此外还有两特别的地方需要注意:一、同为关系运算符,但 =和!=的级别低于其它四个;二、第2组与第13组的操作符是右结合的,其它的都为左结合;通过分类我们大大减少了需要记忆的内容,遇到使用操作符的时候,我们只需想想它们是什么类型的运算符就可以确定它们之间的相对优先级,从而避免一些不必要的错误。提起运算符的优先级, 很多了解C+的过来人都会想:这有什么难的?不就是谁的优先 级高就算谁么。确实如此,运算符的优先级不是一个大问题,但对于一个初学者来说,却经常容易在上面迷糊与犯错。而对于一个了解C+的人来说,我相信也会偶尔在上面摔倒,不信就继续往下读。“优先级高的先运算”带来的困惑C+中运算符的优先级有
3、一张表,表里把运算符进行了分类,这张表是不需要死记硬背 的,只要有个大致的轮廓就ok 了。例如应该记住最低优先级是逗号运算符,其次是赋值运算符,再其次是三目运算符。 而关系运算符的优先级高于逻辑运算符(不包括逻辑非运算),算术运算符的优先级高于关系运算符,象+和-的优先级比前面几个都高,但最高的要属()了。知道这些后,你的脑海里一定有一条准则了:优先级高的先运算。那么下面看一 个例子:intx=1,y=0;!x&&x+y&&+y;上面的语句中出现了! 、&&、+、+这四个运算符,那么问题来了,到底先算谁呢?有一个姓蔡的同学站起来说,+运算符在这里
4、面优先级最高,理所应当最先算 +,既先计算+y,再算!x,再算x+y,最后把它们&&起来。按照蔡同学的思路,第二步的结果是 0&&x+y&&1 ,由于&&是严格运算,有一个为0结果既为0,所以不需要计算x+y 了,整个 语句的结果是:假。按照上面蔡同学的说法,执行完后y的值应该是1 了,这对不对呢?一位姓高的同学站起来反驳道, 我觉得应该先计算!x,如果值为假,则不需要计算下去, 最后结果为假。如果值为真,再计算 x+y,同理如果其值为真,再去计算 +y,否则最后结 果也为假。蔡同学不服起来说,高同学你觉得+和!谁的优先级高呢?高
5、同学答道,那当然是+高。蔡同学接着问,那为什么还要先计算!呢?高同学答不出来了。是呀,为什么要先算!呢?加括号确定优先级的方法高同学说的是正确的, 为什么呢?下面我给大家解释一下。当多个优先级不同的运算符在一起时,为了不混淆,可以先加上括号,这样就分出层次了,相同层次的考虑结合性问题, 当确定下来先算那块时,再往这块里面深入。 例如上面的例子,我们可以这样加上括号:从左向右看,由于!比&&优先级高,所以有(!x),又由于&&比+优先级低,所以有(x+y),而+ 优先级高于&&,所以(+y)。这样整个式子就变成了:(!x)&&(x+
6、y)&&(+y), 最外层的是两个&&运算,由于&&的结合性是从左至右,所以上式可看成:a&&b&&c,先计算a,再计算b,最后算c。由于x=1,则就为假,后面的就不需要再算了,整个语句的值为假。执行 完后,y的值没变,还是0。所以碰到不清楚先算谁后算谁时, 先加个括号看看,就明白了先后次序。 下面做一个加 括号的练习:给语句 c=a>b?a:b;加括号。此语句有三个运算符: =、>、?:,应该怎样加括号 呢?第一种方案:c=(a>b)?a:b);第二种方案:c=(a>(b?a:b);第三种
7、方案:(c=a)>(b?a:b);应该是那一种呢?按照运算符优先级的高低顺序,>优先级高于=,所以不可能把(c=a)括起来。而 >优先级高于?:运算符。所以也不可能把(b?a:b)括起来。因此,第一种答案正确。下面再看一个类似的例子:inti=8,j=4,k;k=i<j?+i:+j;猛然一看,有些人上来可能就要计算+i和+j 了。这里不妨先加括号看看。从左至右看,的优先级高于=而且又高于?:,所以有k=(i<j)?+i:+j,再继续向右看,由于+高于?:, 所以k=(i<j)?(+i):(+j),这样相当于k=a?b:c,先算a的值,若为真,则值为b,即算一
8、下+i, 若为假,贝U值为c,即算一下+j。整个语句执行完后,k的值为5, i的值为8, j的值为5。每个操作符拥有某一级别的优先级, 同时也拥有左结合性或右结合性。 优先级决定一个 不含括号的表达式中操作数之间的“紧密”程度。例如,在表达式ab+c中,乘法运算的优先级高于加法运算符的优先级,所以先执行乘法ab,而不是加法b+c。但是,许多操作符的优先级都是相同的。这时,操作符的结合性就开始发挥作用了。在表达式中如果有几个优先级相同的操作符,结合性就起仲裁的作用,由它决定哪个操作符先执行。像下面这个表达式:inta,b=1,c=2;a=b=c;我们发现,这个表达式只有赋值符,这样优秀级就无法帮
9、助我们决定哪个操作先执行, 是先执行b=c呢?还是先执行a=b。如果按前者,a=结果为2,如果按后者,a的结果为1。所以的赋值符(包括复合赋值)都具有右结合性,就是说在表达式中最右边的操作最先 执行,然后从右到左依次执行。这样,c先赋值给b,然后b在赋值给a,最终a的值是2.类似地,具有左结合性的操作符(如位操作符“&”和“”)则是从左至右依次执行。结合性只用于表达式中出现两个以上相同优先级的操作符的情况,用于消除歧义。事实上你会注意到所有优先级相同的操作符,他们的结合性也相同。这是必须如此的,否则结合性依然无法消除歧义,如果在计算表达式的值时需要考虑结合性,那么最好把这个表达式一分为
10、二或者使用括号。裘宗燕:c/c+语言中的表达式求值经常可以在一些讨论组里看到下面的提问:“谁知道下面c语句给n赋什么值? ”m=1;n=m+m+;最近有位不相识的朋友发email给我,问为什么在某个 c+系统里,下面表达式打印出两个4,而不是4和5:a=4;cout<<a+<<a;c+不是规定 <<操作左结合吗?是 C+书上写错了,还是这个系统的实现有问题?要弄清这些,需要理解的一个问题是:如果程序里某处修改了一个变量(通过赋值、增量/减量操作等),什么时候从该变量能够取到新值?有人可能说,"这算什么问题!我修改了变量,再从这个变量取值,取到的当然
11、是修改后的值!”其实事情并不这么简单。C/C+语言是“基于表达式的语言”,所有计算(包括赋值)都在表达式里完成。“x=1;”就是表达式“ x=1”后加表示语句结束的分号。要弄清程序的意义,首先要理解表达式的意 义,也就是:1)表达式所确定的计算过程;2)它对环境(可以把环境看作当时可用的所有变量)的影响。如果一个表达式(或子表达式)只计算出值而不改变环境,我们就说它是引 用透明的,这种表达式早算晚算对其他计算没有影响(不改变计算的环境。当然,它的值可能受到其他计算的影响)。如果一个表达式不仅算出一个值,还修改了环境,就说这个表达 式有副作用(因为它多做了额外的事)。a+就是有副作用的表达式。这
12、些说法也适用于其他语言里的类似问题。现在问题变成:如果 C/C+程序里的某个表达式(部分)有副作用,这种副作用何时才 能实际体现到使用中?为使问题更清楚,我们假定程序里有代码片段“.ai+.aj. ”,假定当时i与j的值恰好相等(ai和aj正好引用同一数组元素);假定ai+确实在aj之前 计算;再假定其间没有其他修改ai的动作。在这些假定下,ai+对ai的修改能反映到aj的求值中吗?注意:由于 i与j相等的问题无法静态判定,在目标代码里,这两个数组元素 访问(对内存的访问)必然通过两段独立代码完成。现代计算机的计算都在寄存器里做,问 题现在变成:在取aj值的代码执行之前,ai更新的值是否已经被
13、(从寄存器)保存到内存? 如果了解语言在这方面的规定,这个问题的答案就清楚了。程序语言通常都规定了执行中变量修改的最晚实现时刻(称为顺序点、序点或执行点)。程序执行中存在一系列顺序点(时刻),语言保证一旦执行到达一个顺序点,在此之前发生的所有修改(副作用)都必须实现(必须反应到随后对同一存储位置的访问中),在此之后的所有修改都还没有发生。在顺序点之间则没有任何保证。对C/C+语言这类允许表达式有副作用的语言,顺序点的概念特别重要。现在上面问题的回答已经很清楚了:如果在ai+和aj之间存在一个顺序点,那么就能保证aj将取得修改之后的值;否则就不能保证。C/C+语言定义(语言的参考手册)明确定义了
14、顺序点的概念。顺序点位于:1. 每个完整表达式结束时。完整表达式包括变量初始化表达式,表达式语句,return语句的表达式,以及条件、循环和switch语句的控制表达式(for头部有三个控制表达式);2. 运算符&&、?:和逗号运算符的第一个运算对象计算之后;3. 函数调用中对所有实际参数和函数名表达式(需要调用的函数也可能通过表达式描述)的求值完成之后(进入函数体之前)。假设时刻ti和ti+1是前后相继的两个顺序点,到了 ti+1,任何c/c+系统(vc、bc等都 是c/c+系统)都必须实现ti之后发生的所有副作用。当然它们也可以不等到时刻ti+1 ,完全可以选择在时段t,t
15、i+1之间的任何时刻实现在此期间出现的副作用,因为c/c+语言允许这些选择。前面讨论中假定了 ai+在ai之前做。在一个程序片段里ai+究竟是否先做,还与它所在的表达式确定的计算过程有关。我们都熟悉c/c+语言有关优先级、结合性和括号的规定,而出现多个运算对象时的计算顺序却常常被人们忽略。看下面例子:(a+b)(c+d)fun(a+,b,a+5)这里“”的两个运算对象中哪个先算?fun及其三个参数按什么顺序计算?对第一个表达式,采用任何计算顺序都没关系,因为其中的子表达式都是引用透明的。第二个例子里的实参表达式出现了副作用,计算顺序就非常重要了。少数语言明确规定了运算对象的计算顺序(java规
16、定从左到右),c/c+则有意不予规定,既没有规定大多数二元运算的两个对象的 计算顺序(除了 &&、和,),也没有规定函数参数和被调函数的计算顺序。在计算第二个表 达式时,首先按照某种顺序算fun、a+、b和a+5,之后是顺序点,而后进入函数执行。不少书籍在这些问题上有错(包括一些很流行的书)。例如说c/c+先算左边(或右边),或者说某个c/c+系统先计算某一边。这些说法都是错误的! 一个c/c+系统可以永远先算左边或永远先算右边, 也可以有时先算左边有时先算右边,或在同一表达式里有时先算左边有时先算右边。不同系统可能采用不同的顺序(因为都符合语言标准);同一系统的不同版本完全可
17、以采用不同方式;同一版本在不同优化方式下,在不同位置都可能采用不同顺序。 因为这些做法都符合语言规范。在这里还要注意顺序点的问题:即使某一边的表达式先算了,其副作用也可能没有反映到内存,因此对另一边的计算没有影响。回到前面的例子:“谁知道下面c语句给n赋什么值?”m=1;n=m+m+;正确回答是:不知道!语言没有规定它应该算出什么,结果完全依赖具体系统在具体上下文中的具体处理。其中牵涉到运算对象的求值顺序和变量修改的实现时刻问题。对于:cout<<a+<<a;我们知道它是(cout.operator<<(a+).operator<<(a);的简写
18、。先看外层函数调用,这里需要算出所用函数(由加下划线的一段得到),还需要计算a的值。语言没有规定哪个先算。如果真的先算函数,这一计算中出现了另一次函数 调用,在被调函数体执行前有一个顺序点,那时a+的副作用就会实现。如果是先算参数,求出a的值4,而后计算函数时的副作用当然不会改变它(这种情况下输出两个4)。当然, 这些只是假设,实际应该说的是:这种东西根本不该写,讨论其效果没有意义。有人可能说,为什么人们设计 C/C+时不把顺序规定清楚, 免去这些麻烦? C/C+语言的 做法完全是有意而为,其目的就是允许编译器采用任何求值顺序,使编译器在优化中可以根据需要调整实现表达式求值的指令序列,以得到效率更高的代码。像java那样严格规定表达式的求值顺序和效果,不仅限制了语言的实现方式,还要求更频繁的内存访问(以实现副作用),这些可能带来可观的效率损失。应该说,在这个问题上,C/C+和java的选择都贯彻了它们各自的设计原则,各有所获(C/C+潜在的效率,java更清晰的程序行为),当然也都有所失。还应
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年陕西省安康地区单招职业倾向性考试题库附答案
- 2025江苏无锡市宜兴市部分机关事业单位招聘编外人员3人(B类)笔试考试参考试题及答案解析
- 金融投资顾问面试题集
- 2025内蒙古北疆交通天然气有限公司招聘6人考试笔试参考题库附答案解析
- 中国物流2026届校园招聘笔试考试参考试题及答案解析
- 吉安市市直机关事业单位编外工作人员招聘(四十九)招聘人数核减考试笔试模拟试题及答案解析
- 2025年深圳开放大学辅导员招聘备考题库附答案
- 2025年湖南冶金职业技术学院辅导员招聘备考题库附答案
- 物资管理部面试题集
- 船体焊接工技能等级考试题
- 中国淋巴瘤治疗指南(2025年版)
- 2025年云南省人民检察院聘用制书记员招聘(22人)考试笔试模拟试题及答案解析
- 2026年空气污染监测方法培训课件
- 实习2025年实习实习期转正协议合同
- 疗伤旅馆商业计划书
- 2025西部机场集团航空物流有限公司招聘考试笔试备考题库及答案解析
- 2025年广西公需科目答案6卷
- 四年级《上下五千年》阅读测试题及答案
- 江苏省五高等职业教育计算机网络技术专业指导性人才培养方案
- GB/T 35347-2017机动车安全技术检测站
- 急性呼吸窘迫综合征
评论
0/150
提交评论