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

问题描述 投票:0回答:4

方案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 的行为很奇怪?

c++ operators expression
4个回答
3
投票

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

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( )由于运算符+的从左到右关联性,但是对 f3 的函数调用可以在运行时首先、最后或在 f1() 或 f2() 之间进行计算

重点是我的。


0
投票

三个独立的概念经常被混淆:

求值顺序,决定了操作数的求值顺序。

标准中通常未指定这一点。

优先级,它确定两个运算符中的哪一个首先被评估。

例如,在

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

关联性,它决定首先评估哪个运算符具有相同的优先级

例如,

<<
是左结合的;
a << b << c
被评估为
(a << b) << c
,而赋值是右关联的;
a = b = c
a = (b = c)

操作数的求值顺序也不受结合性的影响。


-2
投票

该类型的评估顺序在标准中没有规定。由编译器来进行它正在做的优化。

© www.soinside.com 2019 - 2024. All rights reserved.