【问题标题】:C++ Precedence definitive list [closed]C ++优先级最终列表[关闭]
【发布时间】:2015-05-16 14:17:33
【问题描述】:

快速搜索 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 是一个 reexpr,显然括号中的括号使表达式无效。

(*p)++;

我读到后增量高于前增量,所以我将它放在 () [] 等下面。是什么使它相等(如果是)?

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

throw x += 5;

大概应该先计算 x += 5 然后再投掷。 learncpp 不同,第三个来源根本没有提到 throw 作为运算符。

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

任何能够照亮优先表位的 cmets 在这里都会很棒。

【问题讨论】:

  • “这显然是错误的,因为:throw x += 5; 应该先计算 x += 5,然后再抛出。”它们具有相同的优先级并没有错。它们具有从右到左的关联性。如果要添加虚括号,则解析为throw (x += 5);
  • 在C++中,运算符优先级实际上是根据语法定义的。您引用的引用在不同的地方有?:,但是像x ? y : z = 5 这样的操作将被解析为(x) ? (y) : (z = 5),不是因为优先级而是因为conditional-expression 可以是logical-或表达式 ? 表达式 : 赋值表达式.
  • certainly disagree 和 learncpp 把 ?: 上面的作业。标准(或至少 N3936)表示它也从右到左分组,而不是从左到右。
  • @chris b=5 在您的第一个示例中是 ?: 的一部分,请在您之前查看我的评论。
  • 请注意,您的第一个问题(是否有一个好的、明确的优先级总结)是题外话,因为您要求的是场外资源。有趣的是,询问优先级表本身将成为话题,因为回答者可以在其答案中重现该表,因此您可能需要编辑您的问题。

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


【解决方案1】:

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

throw, ?: 和 C++ 中的所有赋值都是语法产生式assignment-expression中的替代项,定义如下

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

其中条件表达式定义为逻辑或表达式 ? 表达式 : assignment-expressioninitializer-clause 是另一个 assignment-expression(当它不是 braced-init- list),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)

【讨论】:

  • 很好的答案:)。但是,优先级与递归分析究竟有何不同?当我们人类分析一个表达式时。说8 * 5 + 7 * 3。我们将其拆分,并首先解析(读取:计算)乘法。那是递归的吧?
【解决方案2】:

查看您的三个来源,顺序基本相同 - C++ 参考组 throw 和 ?: 以及赋值,这在 learncpp 中是分开的。 Purdue 的要简单得多,但也不那么具体。

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

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

(x+1)++;

当然不会做任何事情,因为 (x+1) 返回一个 r 值,它不能由 ++ 运算符分配。

(*p)++;

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

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

++(*x);

在这种情况下,x 必须在递增之前先被取消引用。

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

throw x += 5;

将评估为

throw (x += 5);

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

【讨论】:

  • throw 确实是运营商。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 1970-01-01
  • 2020-10-20
相关资源
最近更新 更多