表达式的求值顺序 我刚刚读到,操作符的评价和优先级顺序不同,但是C++中的相关概念是不同的。但我仍然不清楚它们之间有什么区别,但又有什么联系 int x = c + a * b; // 31 int y = (c + a) * b; // 36

表达式的求值顺序 我刚刚读到,操作符的评价和优先级顺序不同,但是C++中的相关概念是不同的。但我仍然不清楚它们之间有什么区别,但又有什么联系 int x = c + a * b; // 31 int y = (c + a) * b; // 36,c++,evaluation,operator-precedence,C++,Evaluation,Operator Precedence,上述陈述与评估顺序有什么关系。e、 当我说(c+a)我是否通过改变表达式的优先级来改变表达式的求值顺序?答案是may或may not a、b和c的求值顺序取决于编译器对此公式的解释。求值顺序是指当同一表达式中的不同子表达式相对彼此求值时 例如在 3 * f(x) + 2 * g(x, y) 乘法和加法之间有通常的优先规则。但我们有一个评估问题的顺序:第一次乘法是发生在第二次乘法之前,还是第二次乘法发生在第一次乘法之前?这很重要,因为如果f()有一个改变y的副作用,整个表达式的结果将根据操作顺序

上述陈述与评估顺序有什么关系。e、 当我说
(c+a)
我是否通过改变表达式的优先级来改变表达式的求值顺序?

答案是may或may not

a、b和c的求值顺序取决于编译器对此公式的解释。

求值顺序是指当同一表达式中的不同子表达式相对彼此求值时

例如在

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


在您的特定示例中,这种求值顺序场景(结果值取决于顺序)不会出现。

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

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

使用
()
唯一要改变的是表达式的数学含义。假设
a
b
c
都是
2
a+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;
这也将产生正确的结果(假设没有与溢出相关的问题)。在这种情况下,实际的评估计划甚至远不像您在源代码中编写的那样

简言之,假设实际的评估结果与您在程序源代码中编写的内容有任何显著的相似性,这充其量是幼稚的。尽管人们普遍认为,内置操作符通常不会被翻译成机器的“对应项”


上述情况同样适用于内置操作符。一旦我们开始处理重载运算符,情况就会发生巨大变化。重载运算符确实完全按照表达式的语义结构进行计算。即使重载操作符也有一定的自由度,但它不像内置操作符那样不受限制。

评估顺序的重要部分是组件是否有副作用

假设你有:

int i = c() + a() * b();
其中
a
b
有副作用:

int global = 1;

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

在本例中,最可能的结果是

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


    简而言之,优先级告诉您运算符应用于参数的顺序(
    *
    +
    之前),而求值顺序告诉您参数的解析顺序(
    a()
    b()
    c()
    )。这就是它们“不同但相关”的原因。

    考虑以下示例:

    #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=1+U最大值+1.0;
    双b=1+1.0+UINT_最大值;
    printf(“a=%g\n”,a);
    printf(“b=%g\n”,b);
    返回0;
    }
    
    在这里,就我们所知的数学而言,a和b的计算是相等的,并且必须有相同的结果。但在C(++)世界中这是真的吗?查看程序的输出。

    关于这个问题,我想介绍一些值得一读的内容。
    规则3和4提到了序列点,这是另一个值得记住的概念。

    正如其他人所说,求值顺序不同于优先规则。这是真的。。。但是
    a
    b
    值的差异与整体升级规则有关,而不是与评估顺序有关。@YSC该顺序决定转换/升级。