c++优先级确定列表

C++ Precedence definitive list

本文关键字:列表 优先级 c++      更新时间:2023-10-16

快速搜索c++优先级需要多次尝试。令人不安的是,它们都是不同的。大多数肯定是错误的,尽管是在一些小细节上。

我将包括三个。第一个来自cppreference.com网站,声称有16个优先级。Learn.cpp有18个。普渡大学的一张更简单的表格要简单得多。

http://en.cppreference.com/w/cpp/language/operator_precedence

http://www.learncpp.com/cpp-tutorial/31-precedence-and-associativity/

http://web.ics.purdue.edu/cs240/misc/operators.html

这些都不是确定的,但是当我看ISO标准草案时,http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf它甚至没有一个表格,说明你可以从上下文中找出它。

我的问题是1)是否有一个好的,明确的优先级总结?

2)谁能评论一下这些表格传达的所有不同的"事实"?

例如,前两个都同意后自增/自减与括号在同一层,这在实践中意味着什么?

(x+1)++

没有意义,因为x+1是一个正则表达式,很明显,把表达式括起来的括号使后增量无效。

(*p)++;

我读到后增量比预增量高,所以我会把它放在()[]等下面。是什么使它相等(如果相等的话)?

cppreference声明throw与赋值操作符在同一层。这显然是错误的,因为:

throw x += 5;

应该在抛出之前先计算x += 5。Learncpp不同,第三个源代码根本没有提到throw作为操作符。

这是我第一次看到作为一个操作符。我承认没有研究标准多年,但回报是一个声明,为什么不扔?

优先级不是语言规范的一部分。它是我们人类使用的一种助记器,用来理解表达式的含义,而不需要像真正的解析器那样递归地分析它。

throw、?:和c++中的所有赋值都是语法生成赋值表达式的替代,定义如下

 assignment-expression:
    conditional-expression
    logical-or-expression assignment-operator initializer-clause
    throw-expression

其中条件表达式定义为逻辑或表达式?expression:赋值表达式初始化子句是另一个赋值表达式(当它不是带括号的初始化列表时),抛出表达式定义为关键字throw后跟可选的assignment-expression

用人类的术语来说,我们将其描述为"相同的优先级,从右向左分组"。

要重用cppreference示例,

e = a < d ? a++ : a = d解析为e = ((a < d) ? (a++) : (a = d))

false ? 7 : throw 3解析为false ? 7 : (throw 3),是的,您的throw x += 5示例解析为throw (x += 5)

查看您的三个源代码,顺序基本上是相同的- c++引用组throw和?:与赋值一起,这在learncpp中是分开的。普渡大学的方法简单得多,但也不那么具体。

虽然它可能看起来有点复杂,但我建议使用learncpp’s作为指导方针,因为它是最具体的。括号规则有点令人困惑;作为一个经验法则,使用它们就好像它们具有最高的优先级。

关于你问题的第二部分……

(x+1)++;

当然不会做任何事情,因为(x+1)返回一个r值,不能被++操作符赋值。

(*p)++;

对指针p解引用,然后对它所指向的变量加1。因为解引用小于自增,如果没有括号,它将解引用p,然后增加指针,导致未定义的行为。

我认为它实际上写成这样的后增量与()相同的原因是括号无论如何都会先完成。当然,如果()的计算结果是r值,它将返回一个错误。预增量较低,因为如果需要,()必须先执行。例如,

++(*x);

在这种情况下,必须先对x解引用,然后再对其加1。

对于你关于throw的最后一个问题,表中将其列为从右向左计算。您的

代码片段
throw x += 5;

将计算为

throw (x += 5);

被列为操作符,因为它显然是一个表达式。其他更了解异常处理的人可能会解释这个