C ++ Precedence权威列表

时间:2015-05-16 14:17:34

标签: c++ operators language-lawyer operator-precedence

快速搜索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是一个rexpr,显然括号表达式括号使后增量无效。

(*p)++;

我已经读过,后增量高于预增量,所以我会把它放在下面()[]等。是什么使它相等(如果是)?

cppreference声称throw与赋值运算符处于同一级别。这似乎显然是错误的,因为:

throw x += 5;

应该在投掷之前首先计算x + = 5。 learncpp不同,第三个来源根本没有提到作为运算符抛出。

这是我第一次见到运营商。我承认多年来没有研究这个标准,但回报是一个声明,为什么不扔?

任何有关优先级表位的评论都会很棒。

2 个答案:

答案 0 :(得分:4)

优先顺序不是语言规范的一部分。它是我们人类使用的助记符设备,用于理解表达式的含义,而不像实际的解析器那样递归地分析它。

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

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

条件表达式定义为 logical-or-expression 表达式 :< / strong> assignment-expression initializer-clause 是另一个赋值表达式(当它不是 braced-init-时列表), throw-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)

答案 1 :(得分:0)

看看你的三个来源,顺序基本相同--C ++参考组抛出和?:与赋值一起,它在learncpp中是独立的。普渡大学更简单,但也不那么具体。

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

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

(x+1)++;

肯定不会做任何事情,因为(x + 1)返回一个r值,而不能由++运算符赋值。

(*p)++;

取消引用指针p,然后递增它指向的变量。因为取消引用低于增量,没有括号,它将取消引用p然后递增指针,从而导致未定义的行为。

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

++(*x);

在这种情况下,必须先取消引用x,然后才能递增它。

关于throw的最后一个问题,表格将其列为从右到左的评估。

的片段
throw x += 5;

将评估为

throw (x += 5);

它被列为运营商,因为它显然是一种表达方式。对异常处理有更多了解的其他人可能会解释这一点。