2011-10-01 149 views
3

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

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

上述说明与评估顺序有什么关系。例如,当我说(c + a)上午我改变其优先顺序来改变表达式评估的顺序?

回答

6

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

假设你有这样的:

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

但编译器可以自由选择wh atever命令它想要的。

的短篇小说是优先告诉你在哪个运营商的应用参数(*+之前)的顺序,而为了评估的告诉你在什么样的顺序参数都解决了(a()b()c() )。这就是为什么他们“不同但相关”。

0

答案可能会也可能不会。

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

+1

正如其他人所说,评估顺序不同于优先规则。 – dp2

3

“评价顺序”是指当相同表达式中的不同子表达相对于彼此被计算时。

例如在

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

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

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

1

只要我们谈论内置操作员:不,您不会通过使用()来更改评估顺序。您无法控制评估顺序。事实上,这里根本没有“评估顺序”。

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

您使用()更改的唯一内容就是表达式的数学含义。假设a,bc都是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; 

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

简而言之,假设实际评估与您程序源代码中所写内容的任何显着相似性都是天真的。尽管人们普遍认为,内置的操作员通常不会被翻译成他们的机器“同行”。

以上内容适用于内置的操作员。一旦我们开始处理超载的操作员,事情就会发生巨大的变化。确实根据表达式的语义结构评估了重载操作符。即使对于重载操作员也有一些自由,但它不像内置操作员那样不受限制。

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(++)世界中,这是真的吗?查看程序的输出。

+0

这是真的......但是'a'和'b'的值的差异与积分促销规则而不是评估顺序有关。 – YSC

+0

@YSC订单决定转换/促销。 –

0

我想介绍一下a link这个问题。 规则3和4提到约sequence point,另一个值得记住的概念。