上节《编程语法分析之从表达式说起》中说到表达式,他的主要作用就是返回一个值!那这个值具体是多少,就要看表达式的整个运算过程。要理解表达式的运算过程就必须了解“优先级”和“结合律”。

之前讲到表达式,一般有操作数和操作符(或者叫做运算符)组成。“优先级”和“结合律”都是针对操作数和操作符来分析的。现在就来看张表:

 

这张表介绍了“优先级”和“结合律”,优先级数字越小,优先级越高。在优先级相同的情况下,才会考虑“结合律”!

注意上表中,结合方向一栏,右到左的意思就是右结合,左到右,就是左结合。简单说,“结合律”就仅仅分为“左结合”与“右结合”!

为了很好的理解“优先级”和“结合律”我举几个有意义的例子。

 

例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));

编程语法分析之“优先级”和“结合律”的更多相关文章

  1. 高质量C++/C编程指南(林锐)

    推荐-高质量C++/C编程指南(林锐) 版本/状态 作者 参与者 起止日期 备注 V 0.9 草稿文件 林锐   2001-7-1至 2001-7-18 林锐起草 V 1.0 正式文件 林锐   20 ...

  2. 中兴软件编程规范C/C++

    Q/ZX 深圳市中兴通讯股份有限公司企业标准 (设计技术标准) Q/ZX 04.302.1–2003      软件编程规范C/C++                               20 ...

  3. 高质量c c++编程

    第1章 文件结构 每一个C++/C程序通常分为两个文件.一个文件用于保存程序的声明(declaration),称为头文件.还有一个文件用于保存程序的实现(implementation),称为定义(de ...

  4. .NET编程规范

    .NET开发编程规范 第1章 程序的版式 版式虽然不会影响程序的功能,但会影响可读性.程序的版式追求清晰.美观,是程序风格的重要构成因素. 可以把程序的版式比喻为"书法".好的&q ...

  5. [3]第二章 C++编程简介

    (本资料均从 internet 上进行收录整理,若要转载,请与原作者联系) 2.1  机器语言.汇编语言和高级语言 程序员用各种编程语言编写指令,有些是计算机直接理解的,有些则需要中间翻译(tranl ...

  6. 高质量C++/C编程指南

    http://man.chinaunix.net/develop/c&c++/c/c.htm#_Toc520634042 高质量C++/C编程指南 文件状态 [  ] 草稿文件 [√] 正式文 ...

  7. C++编程指南续

    三. 命名规则 比较著名的命名规则当推Microsoft公司的"匈牙利"法,该命名规则的主要思想是"在变量和函数名中加入前缀以增进人们对程序的理解".例如所有的 ...

  8. Java开发笔记(十四)几种运算符的优先级顺序

    到目前为止,我们已经学习了Java语言的好几种运算符,包括算术运算符.赋值运算符.逻辑运算符.关系运算符等基础运算符,并且在书写赋值语句时都没添加圆括号,显然是默认了先完成算术.逻辑.关系等运算,最后 ...

  9. C、C++基础和编程风格 (转)

    原文链接 作者:寒小阳时间:2013年8月.出处:http://blog.csdn.net/han_xiaoyang/article/details/10515417.声明:版权所有,转载请注明出处, ...

随机推荐

  1. Android--播放Gif的取巧办法

    由于做的项目,要有个动画的等待效果,第一时间想到的就是Gif(懒,省事),但是试了好多据说能播放Gif的控件,也写过,但是放到魅族手机上就是不能播放,所有就想了个招,既然Gif能在浏览器上播放,那an ...

  2. 【疑难杂症02】ResultSet.next() 效率低下问题解决

    今天帮同事解决了一个问题,记录一下,帮助有需要的人. 一.问题解决经过 事情的经过是这样的,下午我在敲代码的时候,一个同事悄悄走到我身边,问我有没有用没用过Oracle,这下我蒙了,难道我在他们眼中这 ...

  3. TFS命令行操作

    前言 本文主要介绍如何通过TFS(Team Foundation Server)命令行强制解锁(UnDo)项目成员对项目文件的占用. 正文 在多人同时开发项目的时候,如果遇到项目组成员独占签出文件后未 ...

  4. sshpass 绕过ssh 密码交互式验证

    经常我们使用脚本登入服务器的时候,如果使用ssh 命令,经常会提示密码输入,我们不得不手动输入密码,因为ssh 没有 密码的选项. 为了能绕过交互式验证,我们使用sshpass命令解决这个问题: 1. ...

  5. Django之cookie&session

    cookie Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式.Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息 ...

  6. java实现安全证书相关操作

    https://blog.csdn.net/zhushanzhi/article/details/77864516 版权声明:本文为博主原创文章,未经博主允许不得转载. package test; i ...

  7. yum 私有仓库

    参考地址:https://blog.oldboyedu.com/autodeploy-yum YUM主要用于自动安装.升级rpm软件包,它能自动查找并解决rpm包之间的依赖关系.要成功的使用YUM工具 ...

  8. 题解 P1034 【矩形覆盖】

    题面 在平面上有n个点(n≤50),每个点用一对整数坐标表示.例如:当n=4时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用k个矩形(1≤ ...

  9. 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 ...

  10. vue2.0路由切换后页面滚动位置不变BUG

    最近项目中遇到这样一个问题,vue切换路由,页面到顶端的滚动距离仍会保持不变.  方法一: 监听路由 // app.vue export default { watch:{ '$route':func ...