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

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

 

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

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

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

 

例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. 【转】设置Qt应用程序图标及应用程序名

    一直以来很纠结给qt应用程序添加图标问题,在网上收过一次,但是感觉不够完整,现将自己的实现过程记录下,以便以后查看: 通过网上的例子知道qt助手中有相关说明: Setting the Applicat ...

  2. 解释JS变量作用域的范例

    JS的变量作用域只有两种:全局作用域与函数作用域. 用var声明的变量不能简单的说是属于函数作用域,应该是说属于其最近的作用域. var a = 10; function test(){ var a; ...

  3. LeetCode题解之 Implement strStr()

    1.题目描述 2.题目分析 字符串操作,注意边界条件即可. 3.代码 int strStr(string haystack, string needle) { int n = needle.size( ...

  4. Hibernate 批处理

    批处理 考虑一种情况,你需要使用 Hibernate 将大量的数据上传到你的数据库中.以下是使用 Hibernate 来达到这个的代码片段: Session session = SessionFact ...

  5. mysql中删除同一行会经常出现死锁?太可怕了

    之前有一个同事问到我,为什么多个线程同时去做删除同一行数据的操作,老是报死锁,在线上已经出现好多次了,我问了他几个问题:   1. 是不是在一个事务中做了好几件事情?      答:不是,只做一个删除 ...

  6. 虚拟机压力测试延迟高的可能原因及 ILPIP 配置 / 查询脚本

    测试初期 Client VM 的延迟结果正常: 测试后期 Client VM 的延迟偶尔突增/连接失败,越后期超高延迟(比如 30 秒)出现越多: 问题分析 造成这一现象的根本原因很可能是 SNAT( ...

  7. Css基础笔记(部分)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. RHEL6.5安装multipath多路径软件

    一.划zone(以博科光纤交换机为例) ①查看光纤交换机端口状态 RAC_SW_01:admin> switchshow Index Port Address Media Speed State ...

  9. [技术] OIer的C++标准库 : STL入门

    注: 本文主要摘取STL在OI中的常用技巧应用, 所以可能会重点说明容器部分和算法部分, 且不会讨论所有支持的函数/操作并主要讨论 C++11 前支持的特性. 如果需要详细完整的介绍请自行查阅标准文档 ...

  10. SA387Gr91

    SA387Gr91 在DTCMS中,我做了一个SA387Gr91的网站,挺好看的.