编程语法分析之“优先级”和“结合律”
上节《编程语法分析之从表达式说起》中说到表达式,他的主要作用就是返回一个值!那这个值具体是多少,就要看表达式的整个运算过程。要理解表达式的运算过程就必须了解“优先级”和“结合律”。
之前讲到表达式,一般有操作数和操作符(或者叫做运算符)组成。“优先级”和“结合律”都是针对操作数和操作符来分析的。现在就来看张表:


这张表介绍了“优先级”和“结合律”,优先级数字越小,优先级越高。在优先级相同的情况下,才会考虑“结合律”!
注意上表中,结合方向一栏,右到左的意思就是右结合,左到右,就是左结合。简单说,“结合律”就仅仅分为“左结合”与“右结合”!
为了很好的理解“优先级”和“结合律”我举几个有意义的例子。
例1、这个例子主要从“结合律”出发,讨论左结合与右结合的特点。
所谓结合,就是多个东西结合成为一个整体,而成为一个新的东西。当一个操作符是一个左结合且为双目运算符时,他会把他左边的东西整个当作一个整体并与之结合,右边的只认离他最近的一个。(右结合与之相反)
如:(这是一个C++例子,能很好的理解结合这个概念)
对于第二个<<运算符而言,他会把他左边的全部当中一个整体,及把
当作一个整体,这个整体其实就是个表达式,他是一个值,他的值就是std::cout的值。
而对于第一个<<运算符而言,在他的右边他只认“Hello,World!”及右边的只认离他最近的一个。
在原文<Accelerated C++>中是这么解释的;

如果您多C++不熟悉,我们就来看第二例子:
例2、一个超级简单的表达式,此时你应该有更深的认识:
a + b + c
首先,此表达式中,操作符都是加号,大家优先级相同,所以转而考虑结合性,+是左结合。
所以第一个加号先与a结合,并且只认右边和他最近的b,而对于第二个加号,会把a+b当作一个整体,并与之结合,然后只认右边和他最近的c。结果就是((a) + b) + c 。
如果前两个例子都不过瘾,我们来看第三个例子:
例3、这个例子需要兼而考虑优先级”和“结合律”。
(* ( ( void (*)() )0 ) )()
这里操作符有小括弧——强制转换符(形式上也是小括弧),解引用符,操作数只有一个,就是0;操作符都是针对操作数的。
我们先从0开始看,和0最近的是小括弧,这个小括弧里面是个void (*)()这其实是个类型——函数指针类型,用小括弧把类型括起来,这个小括弧其实是强制转换符。那么( void (*)() )0 这个表达式结合起来,就表示把0,强制转换为函数指针类型。
在往外又是一个小括弧,这个小括弧就是说小括弧内部是一个结合的整体。此时由于( void (*)() )0是一个整体而且表示一个函数指针,所以把( void (*)() )0替换为p,结果就是(* p )(),这句话的意思其实就是利用函数指针p调用函数。而这p其实是指向地址0的。所以这句表达式的副作用就是,让程序指针PC跳到地址0,及完成一个软件复位的功能。
进一步讨论如果,去掉其中的一层括号:
(* ( void (*)() )0 )()
那么一开始有两个操作符针对操作数0,一个是强制转换符(类型),一个是解引用*观察上表可知(类型)和 * 的优先级都是2,优先级相同,而结合性是右结合,简化一下表达式再分析:
(* ( 类型 )0 )()
因为是右结合,所以*会把右边的( 类型 )0当作一个整体,及 ( 类型 )先和0结合,所以结论是去掉这层括号含义不变!
趁热打铁,我们来看第四个例子:
例4、ph->pNext->pNext->pNext->pNext->pNext
这种表达式通常是在链表的访问中见到,别看他这么长其实也就返回是一个值,所以不必怕它。
ph是个头指针,->这个符号查表得知是左结合,及左边的看成整体,右边的只认一个那么ph->pNext就可以被单独分离出来并且结合到一起成为一个整体,
ph->pNext看成整体之后,其实就是返回一个指针,及第0个节点中存放的指针值!而这个指针指向第1个节点。所以ph->pNext可以用p1代替。
剩下的p1->pNext->pNext->pNext->pNext,依照上面的方法如法炮制就得到p2->pNext->pNext->pNext。最终就得到p4->pNext.
如果说ph指向第0个节点,p4->pNext最终的结果其实就是第4个节点中存放的指针值,指针指向第5个节点。这也就是整个表达式的结果。
最后一个例子引入,逗号表达式作为饭后甜点。
例5、逗号表达式
逗号表达式形如:表达式1,表达式2
首先,逗号表达式,也是个表达式,逗号表达式作为整体也返回一个值!
其次,整个逗号表达式的结果为表达式2的结果。
可能有的同学要发问了,那表达式1不是个打酱油的?其实,表达式1一般是为表达式2做个铺垫,如:(从MFC截取的一个例子)

表达式1其实是给str赋值,表达式2就是一个比较语句,那么if只会判断表达式2的结果是否为真,而不会理会表达式1的返回值。
在使用逗号表达式时,一定要注意优先级的问题,因为“,”的优先级比“=”的优先级还要低。
例如:a = 3*5 , a*4; 由于“,”的优先级比“=”的优先级低,所以a = 3*5先结合,算出a等于15,然后a*4得到60.再根据“整个逗号表达式的结果为表达式2的结果”
所以整个表达式(a = 3*5 , a*4)的结果是60.
具体测试方法为:
int a;
printf("%d",(a = 3*5 , a*4));
编程语法分析之“优先级”和“结合律”的更多相关文章
- 高质量C++/C编程指南(林锐)
推荐-高质量C++/C编程指南(林锐) 版本/状态 作者 参与者 起止日期 备注 V 0.9 草稿文件 林锐 2001-7-1至 2001-7-18 林锐起草 V 1.0 正式文件 林锐 20 ...
- 中兴软件编程规范C/C++
Q/ZX 深圳市中兴通讯股份有限公司企业标准 (设计技术标准) Q/ZX 04.302.1–2003 软件编程规范C/C++ 20 ...
- 高质量c c++编程
第1章 文件结构 每一个C++/C程序通常分为两个文件.一个文件用于保存程序的声明(declaration),称为头文件.还有一个文件用于保存程序的实现(implementation),称为定义(de ...
- .NET编程规范
.NET开发编程规范 第1章 程序的版式 版式虽然不会影响程序的功能,但会影响可读性.程序的版式追求清晰.美观,是程序风格的重要构成因素. 可以把程序的版式比喻为"书法".好的&q ...
- [3]第二章 C++编程简介
(本资料均从 internet 上进行收录整理,若要转载,请与原作者联系) 2.1 机器语言.汇编语言和高级语言 程序员用各种编程语言编写指令,有些是计算机直接理解的,有些则需要中间翻译(tranl ...
- 高质量C++/C编程指南
http://man.chinaunix.net/develop/c&c++/c/c.htm#_Toc520634042 高质量C++/C编程指南 文件状态 [ ] 草稿文件 [√] 正式文 ...
- C++编程指南续
三. 命名规则 比较著名的命名规则当推Microsoft公司的"匈牙利"法,该命名规则的主要思想是"在变量和函数名中加入前缀以增进人们对程序的理解".例如所有的 ...
- Java开发笔记(十四)几种运算符的优先级顺序
到目前为止,我们已经学习了Java语言的好几种运算符,包括算术运算符.赋值运算符.逻辑运算符.关系运算符等基础运算符,并且在书写赋值语句时都没添加圆括号,显然是默认了先完成算术.逻辑.关系等运算,最后 ...
- C、C++基础和编程风格 (转)
原文链接 作者:寒小阳时间:2013年8月.出处:http://blog.csdn.net/han_xiaoyang/article/details/10515417.声明:版权所有,转载请注明出处, ...
随机推荐
- Android--播放Gif的取巧办法
由于做的项目,要有个动画的等待效果,第一时间想到的就是Gif(懒,省事),但是试了好多据说能播放Gif的控件,也写过,但是放到魅族手机上就是不能播放,所有就想了个招,既然Gif能在浏览器上播放,那an ...
- 【疑难杂症02】ResultSet.next() 效率低下问题解决
今天帮同事解决了一个问题,记录一下,帮助有需要的人. 一.问题解决经过 事情的经过是这样的,下午我在敲代码的时候,一个同事悄悄走到我身边,问我有没有用没用过Oracle,这下我蒙了,难道我在他们眼中这 ...
- TFS命令行操作
前言 本文主要介绍如何通过TFS(Team Foundation Server)命令行强制解锁(UnDo)项目成员对项目文件的占用. 正文 在多人同时开发项目的时候,如果遇到项目组成员独占签出文件后未 ...
- sshpass 绕过ssh 密码交互式验证
经常我们使用脚本登入服务器的时候,如果使用ssh 命令,经常会提示密码输入,我们不得不手动输入密码,因为ssh 没有 密码的选项. 为了能绕过交互式验证,我们使用sshpass命令解决这个问题: 1. ...
- Django之cookie&session
cookie Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式.Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息 ...
- java实现安全证书相关操作
https://blog.csdn.net/zhushanzhi/article/details/77864516 版权声明:本文为博主原创文章,未经博主允许不得转载. package test; i ...
- yum 私有仓库
参考地址:https://blog.oldboyedu.com/autodeploy-yum YUM主要用于自动安装.升级rpm软件包,它能自动查找并解决rpm包之间的依赖关系.要成功的使用YUM工具 ...
- 题解 P1034 【矩形覆盖】
题面 在平面上有n个点(n≤50),每个点用一对整数坐标表示.例如:当n=4时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用k个矩形(1≤ ...
- Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine
在开发中用到Microsoft.ACE.OLEDB.12.0,但是,出现了Microsoft.ACE.OLEDB.12.0' provider is not registered on the l ...
- vue2.0路由切换后页面滚动位置不变BUG
最近项目中遇到这样一个问题,vue切换路由,页面到顶端的滚动距离仍会保持不变. 方法一: 监听路由 // app.vue export default { watch:{ '$route':func ...