表达评价顺序

时间:2011-10-01 06:27:23

标签: c++ evaluation operator-precedence

我刚才读到,运算符的评估顺序和优先顺序是不同的,但C ++中的相关概念。但我还不清楚这些是如何不同但相关的?

int x = c + a * b;    // 31
int y = (c + a) * b;  // 36

以上陈述与评估顺序有何关系。例如当我说(c + a)时,我是通过更改其优先级来改变表达式的评估顺序吗?

6 个答案:

答案 0 :(得分:8)

关于评估顺序的重要部分是任何组分是否有副作用。

假设你有这个:

int i = c() + a() * b();

ab有副作用:

int global = 1;

int a() {
    return global++;
}
int b() {
    return ++global;
}
int c() {
    return global * 2;
}

编译器可以选择调用a()b()c()的顺序,然后将结果插入表达式中。此时,优先级将接管并决定应用+*运算符的顺序。

在这个例子中,最可能的结果是

  1. 编译器将首先评估c(),然后评估a(),然后评估b(),结果为i = 2 + 1 * 3 = 5
  2. 编译器将首先评估b(),然后评估a(),然后评估c(),结果为i = 6 + 2 * 2 = 10
  3. 但是编译器可以自由选择它想要的任何顺序。

    简短的故事是优先级告诉您运算符应用于参数的顺序(*之前的+),而评估顺序告诉您参数的解析顺序(a()b()c())。这就是为什么它们“不同但相关”。

答案 1 :(得分:3)

“评估顺序”是指同一表达式中的不同子表达式相对于彼此进行评估。

例如在

3 * f(x) + 2 * g(x, y)

你在乘法和加法之间有通常的优先规则。但是我们有一个评估问题的顺序:第一次乘法会在第一次之前发生在第二次或第二次之前吗?这很重要,因为如果f()具有改变y的副作用,则整个表达式的结果将根据操作的顺序而不同。

您的特定示例中,不会出现此评估方案的顺序(其中结果值取决于订单)。

答案 2 :(得分:1)

只要我们讨论内置运算符:不,您不会使用()更改评估顺序。您无法控制评估顺序。事实上,这里根本就没有“评估顺序”。

只要结果正确,就允许编译器以任何方式评估该表达式。甚至不需要使用加法和乘法运算来评估这些表达式。加法和乘法仅存在于程序的文本中。编译器可以完全和完全忽略这些特定操作。在某些硬件平台上,可以通过单个原子机操作来评估这样的表达式。出于这个原因,“评价顺序”的概念在这里没有任何意义。没有什么可以将“秩序”的概念应用到。

使用()进行更改的唯一方法是表达式的数学含义。假设abc都是2a + b * c必须评估为6,而(a + b) * c必须评估为8。而已。这是唯一可以保证的:结果是正确的。如何获得这些结果是完全未知的。只要结果正确,编译器就可以使用绝对任何方法和任何“评估顺序”。

再举一个例子,如果你的程序中有两个这样的表达式,那么

int x = c + a * b;
int y = (c + a) * b;

编译器可以自由地将它们评估为

int x = c + a * b;
int y = c * b + x - c;

也会产生正确的结果(假设没有溢出相关的问题)。在这种情况下,实际的评估计划甚至看起来都不像您在源代码中编写的内容。

简而言之,假设实际评估与你在程序源代码中写的内容有任何重大的相似之处,那就是天真。尽管人们普遍认为,内置运算符通常不会在其机器“对应物”中翻译。

以上内容同样适用于内置运营商。一旦我们开始处理重载运算符,事情就会发生巨大变化。实际上,重载的运算符完全根据表达式的语义结构进行评估。即使有重载运算符,也存在一些自由,但它不像内置运算符那样不受限制。

答案 3 :(得分:0)

答案可能会也可能不会。

a,b和c的评估顺序取决于编译器对该公式的解释。

答案 4 :(得分:0)

考虑以下示例:

#include <limits.h>
#include <stdio.h>
int main(void)
{
    double a = 1 + UINT_MAX + 1.0;
    double b = 1 + 1.0 + UINT_MAX;
    printf("a=%g\n", a);
    printf("b=%g\n", b);
    return 0;
}

在我们所知的数学方面,a和b应该被同等地计算,并且必须具有相同的结果。但是在C(++)世界中是真的吗?查看程序的输出。

答案 5 :(得分:0)

关于这个问题,我想介绍值得阅读的a link。 规则3和规则4提到了sequence point,这是另一个值得记住的概念。