运算符的优先级&同优先级内的结合性&序列点
来源:互联网 发布:linux oracle重建库 编辑:程序博客网 时间:2024/06/05 00:10
运算符的优先级&同优先级内的结合性&序列点
本文以C语言为基础来进行探讨。
参考资料:
运算符的结合性:
https://en.wikipedia.org/wiki/Operator_associativity
c的优先级与结合性:
https://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx
https://msdn.microsoft.com/en-us/library/126fe14k.aspx
http://en.cppreference.com/w/c/language/operator_precedence
http://en.cppreference.com/w/cpp/language/operator_precedence
边效应:
https://msdn.microsoft.com/en-us/library/8a425116.aspx
https://gcc.gnu.org/onlinedocs/gccint/Side-Effects.html
https://gcc.gnu.org/onlinedocs/cpp/Duplication-of-Side-Effects.html
序列点:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf 的附录C
https://msdn.microsoft.com/en-us/library/azk8zbxd.aspx
http://en.cppreference.com/w/cpp/language/eval_order
https://en.wikipedia.org/wiki/Sequence_point
最大匹配:
c语言n1256.pdf 的6.4 Lexical elements第4段落
https://en.wikipedia.org/wiki/Maximal_munch
优先级Precedence
基础知识略。参考Microsoft的C语言文档。
例子:
*p++
: 后缀++
的优先级高于*
,所以解析成*(p++)
而不是(*p)++
a & b || c
: 位与运算符&
的优先级高于||
,所以解析成(a & b) || c
a = b || c
: 解析成a = (b || c)
1 || 0 && 0
解析成1 || (0 && 0)
结果是1q && r || s--
: 解析成(q && r) || (s––)
a.b++
: 解析成(a.b)++
结合性Associativity
结合性就是指,当同等优先级的操作符一起出现时,怎么将操作数和操作符分组(或说绑定)(以确定运算顺序)。
In programming languages, the associativity (or fixity) of an operator is a property that determines how operators of the same precedence are grouped in the absence of parentheses.
If an operand is both preceded and followed by operators (for example, “
^ 4 ^
“), and those operators have equal precedence, then the operand may be used as input to two different operations (i.e. the two operations indicated by the two operators). The choice of which operations to apply the operand to, is determined by the “associativity” of the operators.
注意:结合性只有在出现同等优先级操作符的时候才需要考虑(Associativity is only needed when the operators in an expression have the same precedence)。
一般来讲,操作符的结合性有4种:
- associative (meaning the operations can be grouped arbitrarily)
- left-associative (meaning the operations are grouped from the left)
- right-associative (meaning the operations are grouped from the right)
- non-associative (meaning operations can not be chained, often because the output type is incompatible with the input types)
比如,抽象表达式 a ~ b ~ c
中,~
代表某操作符,其结合性如果:
- left associativity,即从左到右:解析为
(a ~ b) ~ c
- right associativity,即从右到左:解析为
a ~ (b ~ c)
- 其他结合性定义:则其他特殊意义。
代入一个具体的例子,例如 7 − 4 + 2
中,假设+
和-
操作符具有同等优先级,如果:
+
和-
都是左结合性:(7 − 4) + 2 = 5
+
和-
都是右结合性:7 − (4 + 2) = 1
下面是一个更详细的例子,来说明结合性:
表达式 5^4^3^2
,这里 ^
代表幂运算。语法分析器(parser)从左向右扫描读入该表达式。
这里如果幂运算符
^
是右结合性,即从右向左结合顺序,则:- 读入
5
- 读入
^
,现在节点是5^
- 读入
4
,现在节点是5^4
- 读入
^
,现在节点是5^(4^
- 读入
3
,现在节点是5^(4^3
- 读入
^
,现在节点是5^(4^(3^
- 读入
2
,现在节点是5^(4^(3^2
- 没有token可读,结束,现在节点是
5^(4^(3^2))
接下来,进行求值(depth-first),从树最顶端的
^
开始走:- 求值程序(evaluator)沿着树,从第一个、经过第二个、到达第三个
^
表达式 - 计算
3^2=9
,这个结果替换到第二个^
的表达式中 - 继续在parse tree的向上一层,计算
4^9=262144
,同样地这个结果替换到第一个^
表达式中作为其操作数 - 继续向上一层,计算
5^262144=...
得到结果,最后这棵树就可以销毁了并返回总结果 - 结束
- 读入
这里如果幂运算符
^
是左结合性,则计算式被解析成:((5^4)^3)^2
,当然运算结果和上面就不一样了。
序列点Sequence point
边效应Side Effects
略
最大匹配规则Maximal munch
词法分析器读入能构成有意义标记结构的最多的连续输入(the longest sequence of characters that could constitute a preprocessing token)。
例如:
x+++y
: 因为从左向右能构成的最大有意义标记是++
运算符,所以解析成(x++)+y
,而不是x+(++y)
x+++++y
: 同理,被解析成(x++)(++)(+y)
,所以编译报错。
这里需要注意的是“连续输入”。
例如在x+++y
中,三个+
字符是连续的,所以被解析成了(x++)+y
;但如果是x+ ++y
在第一个+
符后面跟了空白,那么一般的词法分析器就会把该语句解析成x+(++y)
。
同理,如果写成x+++ ++y
的表达式,就可以编译通过了。
- 运算符的优先级&同优先级内的结合性&序列点
- 运算符的优先级和结合性
- 运算符的优先级和结合性
- 运算符的优先级和结合 性
- 运算符的优先级和结合性
- 运算符的优先级和结合性
- 运算符的优先级与结合性
- 运算符的优先级和结合性
- 运算符的优先级和结合性
- 运算符的优先级和结合性
- 运算的优先级与结合性
- C运算符的优先级与结合
- C运算符的优先级与结合
- 运算符 优先级 结合性
- C++运算符的优先级和结合性
- C++运算符的优先级和结合性
- 表:运算符的优先级和结合性
- C++运算符的优先级与结合性
- 模板类与类模板、函数模板与模板函数等的区别
- 01 WAMPServer集成环境和安装
- 实现二级列表(实现QQ的好友列表)
- 计算机视觉中常用数据集
- 博客如何使用百度打赏组件?
- 运算符的优先级&同优先级内的结合性&序列点
- TOP K
- Faster-RCNN+VGG用自己的数据集训练模型
- 什么是全角空格?什么是半角空格?
- 关于线程安全的笔记
- 开源JQuery框架 : Prime UI !
- [Java视频笔记]day02
- git 常用命令
- 【慕课笔记】第三章 常用的运算符 第7节 JAVA中运算符的优先级