I've just read that order of evaluation and precedence of operators are different but related concepts in C++. But I'm still unclear how those are different but related?.
int x = c + a * b; // 31
int y = (c + a) * b; // 36
What does the above statements has to with order of evaluation. e.g. when I say (c + a)
am I changing the order of evaluation of expression by changing its precedence?
The important part about order of evaluation is whether any of the components have side effects.
Suppose you have this:
int i = c() + a() * b();
Where a
and b
have side effects:
int global = 1;
int a() {
return global++;
}
int b() {
return ++global;
}
int c() {
return global * 2;
}
The compiler can choose what order to call a()
, b()
and c()
and then insert the results into the expression. At that point, precedence takes over and decides what order to apply the +
and *
operators.
In this example the most likely outcomes are either
- The compiler will evaluate
c()
first, followed bya()
and thenb()
, resulting ini = 2 + 1 * 3 = 5
- The compiler will evaluate
b()
first, followed bya()
and thenc()
, resulting ini = 6 + 2 * 2 = 10
But the compiler is free to choose whatever order it wants.
The short story is that precedence tells you the order in which operators are applied to arguments (*
before +
), whereas order of evaluation tells you in what order the arguments are resolved (a()
, b()
, c()
). This is why they are "different but related".
"Order of evaluation" refers to when different subexpressions within the same expression are evaulated relative to each other.
For example in
3 * f(x) + 2 * g(x, y)
you have the usual precedence rules between multiplication and addition. But we have an order of evaluation question: will the first multiplication happen before the second or the second before the first? It matters because if f() has a side effect that changes y, the result of the whole expression will be different depending on the order of operations.
In your specific example, this order of evaluation scenario (in which the resulting value depends on order) does not arise.
As long as we are talking about built-in operators: no, you are not changing the order of evaluation by using the ()
. You have no control over the order of evaluation. In fact, there's no "order of evaluation" here at all.
The compiler is allowed to evaluate this expression in any way it desires, as long as the result is correct. It is not even required to use addition and multiplication operations to evaluate these expressions. The addition and multiplication only exist in the text of your program. The compiler is free to totally and completely ignore these specific operations. On some hardware platform, such expressions might be evaluated by a single atomic machine operation. For this reason, the notion of "order of evaluation" does not make any sense here. There's nothing there that you can apply the concept of "order" to.
The only thing you are changing by using ()
is the mathematical meaning of the expression. Let's say a
, b
and c
are all 2
. The a + b * c
must evaluate to 6
, while (a + b) * c
must evaluate to to 8
. That's it. This is the only thing that is guaranteed to you: that the results will be correct. How these results are obtained is totally unknown. The compiler might use absolutely anything, any method and any "order of evaluation" as long as the results are correct.
For another example, if you have two such expressions in your program following each other
int x = c + a * b;
int y = (c + a) * b;
the compiler is free to evaluate them as
int x = c + a * b;
int y = c * b + x - c;
which will also produce the correct result (assuming no overflow-related problems). In which case the actual evaluation schedule will not even remotely look like something that you wrote in your source code.
To put it short, to assume that the actual evaluation will have any significant resemblance to what you wrote in the source code of your program is naive at best. Despite popular belief, built-in operators are not generally translated in their machine "counterparts".
The above applies to built-in operators, again. Once we start dealing with overloaded operators, things change drastically. Overloaded operators are indeed evaluated in full accordance with the semantic structure of the expression. There's some freedom there even with overloaded operators, but it is not as unrestricted as in case of built-in operators.
The answer is may or may not.
The evaluation order of a, b and c depends on the compiler's interpretation of this formula.
Consider the below example:
#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;
}
Here in terms of math as we know it, a and b are to be computed equally and must have the same result. But is that true in the C(++) world? See the program's output.
I want to introduce a link worth reading with regard to this question.
The Rules 3 and 4 mention about sequence point
, another concept worth remembering.
来源:https://stackoverflow.com/questions/7618590/order-of-evaluation-of-expression