简体   繁体   中英

operator precedence in C++ expressions

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;
}

output:

20

20

Program 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;
}

output:

x = 50

y = 55

Why does program 1 evaluate fun1() first whereas in program 2 fun() is evaluated last when it is placed at the end of the expression?

From what I understand, C-based languages are left associative so why is program 1 behaving weird?

Historically, order of arguments evaluation of a function call was unspecified. That means that for the call

foo(bar(), baz());

it was left up to the compiler if it needs to call bar() , than baz() , or the other way around. Keep in mind that calling an operator is another case of a generic function call, ie baz() + bar() is semantically the same as operator+(baz(), bar()) .

For practical purposes, compilers used to evaluate arguments from last to first, given the fact that this is the order of pushing arguments to the stack for many function call ABIs.

You mixed 2 concepts (it happens quite often though), let's look to expression:

a = b + c + d * e;

operator precedence and associativity means, that this expression is equal to

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

but it does not mean for example, that d * e must be evaluated before b + c , just because * has higher precedence. Details can be found here order of evaluation

Except where noted below, there is no concept of left-to-right or right-to-left evaluation in C++. This is not to be confused with left-to-right and right-to-left associativity of operators: the expression f1() + f2() + f3() is parsed as (f1() + f2()) + f3() due to left-to-right associativity of operator+, but the function call to f3 may be evaluated first, last, or between f1() or f2() at run time .

emphasis is mine.

There are three separate concepts that frequently get confused:

Evaluation order , which determines in which order operands are evaluated.

This is usually left unspecified in the standard.

Precedence , which determines which of two operators is evaluated first.

For instance, in a + b * c , the multiplication is evaluated before the addition.
The evaluation order of the operands is not affected by precedence.

Associativity , which determines which operator of the same precedence is evaluated first.

For instance, << is left-associative; a << b << c is evaluated as (a << b) << c , while assignment is right-associative; a = b = c is a = (b = c) .
The evaluation order of the operands is not affected by associativity either.

evaluation order of this type are not specified by standard. it is up to the compiler to do the optimization he is doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM