C++表达式中的运算符优先级

operator precedence in C++ expressions

本文关键字:运算符 优先级 表达式 C++      更新时间:2023-10-16

Program 1:

#include <iostream>
using namespace std;
int a = 5;
int fun1() {
    a = 17;
    return 3;
} 
int main() {
// Even though C languages are left associative, 
// this line of code evaluates fun1() first: 
    a = a + fun1();
//  a = 17+3
    printf("%d",a);
    a = fun1()+a;
    printf("n%d",a);
    return 0;
}

输出:

20

20

计划2:

int a = 10;
int fun(){
    a= 15;
    return 30;
}
int main(void) {
// whereas in this example, fun() is evaluated last:
    int x = a + 10 + fun();
//      x = 10 + 10 + 30
    a= 10;
    int y = fun() + 10 + a;
    printf(" x = %d n y = %d n",x,y);
    return 0;
}

输出:

x = 50

y = 55

为什么程序 1 首先计算 fun1((,而在程序 2 中,当 fun(( 放在表达式的末尾时,它被最后计算?

据我了解,基于 C 的语言是联想的,那么为什么程序 1 的行为很奇怪?

从历史上看,函数调用的参数计算顺序是未指定的。这意味着对于通话

foo(bar(), baz());

如果编译器需要调用bar(),则由编译器决定,而不是baz(),或者相反。请记住,调用运算符是泛型函数调用的另一种情况,即 baz() + bar()在语义上与operator+(baz(), bar())相同。

出于实际目的,编译器用于从最后一个到第一个计算参数,因为这是将参数推送到许多函数调用 ABI 的堆栈的顺序。

你混合了 2 个概念(虽然它经常发生(,让我们看看表达式:

a = b + c + d * e;

运算符优先级和结合性意味着此表达式等于

a = ( ( b + c ) + ( d * e ) );

但这并不意味着例如,d * e必须在b + c之前求值,仅仅因为 * 具有更高的优先级。详细信息可在此处找到评估顺序

除下文所述外,C++中没有从左到右或从右到左评估的概念。这不要与运算符的从左到右和从右到左的结合性混淆:表达式 f1(( + f2(( + f3(( 由于运算符 + 的从左到右结合性,表达式 f1(( + f2((( + f3(( 被解析为 (f1(( + f2(((,但对 f3 的函数调用可以在运行时首先、最后或在 f1(( 或 f2(( 之间计算

重点是我的。

有三个不同的概念经常被混淆:

计算顺序,确定计算操作数的顺序。

这通常在标准中没有指定。

优先级,确定首先计算两个运算符中的哪一个。

例如,在a + b * c中,乘法是在加法之前计算的。
操作数的求值顺序不受优先级的影响。

关联性,确定首先计算具有相同优先级的哪个运算符。

例如,<<是左联想的; a << b << c被评估为(a << b) << c,而赋值是右关联; a = b = c a = (b = c).
操作数的求值顺序也不受结合性的影响。

这种类型的求值顺序不是由标准指定的。 由编译器来执行他正在执行的优化。