Will a+b+c be operated like this: a+c+b?
As all we know: the sequence of evalutation is determined by the priority and associativity. For this example,the associativity determined that a+b,then the result plus c. This is what ANSI C compliant compiler do(leave o开发者_开发百科ut the optimization).But will it be evaluated like foregoing manner in the title? In what compiler? In K&R C?
Let me throw this at you:
Operator Precedence vs Order of Evaluation
The compiler is free to rearrange things, as long as the end result is the same.
For example:
1 + b + 1
Can easily be transformed to:
b + 2
The structure of the equation in mathematical terms (in a+(b*c)
we talk about b*c
being evaluated "first") is not necessarily related to the order the compiler will evaluate the arguments
The actual order of execution in this instance is undefined IIRC. C only guarantees that the order of expressions separated by sequence points remains unchanged, and the + operator is not a sequence point.
Most compilers will do what you expect - generating code that will evaluate a then b then c
n1256:
6.5 Expressions
...
3 The grouping of operators and operands is indicated by the syntax.74) Except as specified later (for the function-call()
,&&
,||
,?:
, and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.
...
74) The syntax specifies the precedence of operators in the evaluation of an expression, which is the same as the order of the major subclauses of this subclause, highest precedence first. Thus, for example, the expressions allowed as the operands of the binary+
operator (6.5.6) are those expressions defined in 6.5.1 through 6.5.6. The exceptions are cast expressions (6.5.4) as operands of unary operators (6.5.3), and an operand contained between any of the following pairs of operators: grouping parentheses()
(6.5.1), subscripting brackets[]
(6.5.2.1), function-call parentheses()
(6.5.2.2), and the conditional operator?:
(6.5.15).
Within each major subclause, the operators have the same precedence. Left- or right-associativity is indicated in each subclause by the syntax for the expressions discussed therein.
Emphasis mine. The expression a + b + c
will be evaluated as (a + b) + c
; that is, the result of c
will be added to the result of a + b
. Both a
and b
must be evaluated before a + b
can be evaluated, but a
, b
, and c
can be evaluated in any order.
a + b + c == c + b + a
The order does not matter.
It is called operator precedence
I'll try and highlight the difference between what you consider to be the order of evaluation and what the compiler considers it to be.
Mathematically we say that in the expression a + b * c
, the multiplication is evaluated before the addition. Of course it must be because we need to know what to add to a
.
However, the compiler doesn't necessarily have to consider evaluating the expression b * c
before it evaluates a
. You might think that because multiplication has a higher precedence, then the compiler will look at that part of the expression first. Actually, there is no guarantee about what the compiler will decide to do first. It may evaluate a
first, or b
, or c
. This behaviour is unspecified by the standard.
To demonstrate, let's look at the following code:
#include <iostream>
int f() { std::cout << "f\n"; return 1; }
int g() { std::cout << "g\n"; return 2; }
int h() { std::cout << "h\n"; return 3; }
int main(int argc, const char* argv[])
{
int x = f() + g() * h();
std::cout << x << std::endl;
return 0;
}
Each function, f()
, g()
and h()
, simply outputs the name of the function to the standard output and then returns 1, 2 or 3 respectively.
When the program starts, we initalise a variable x
to be f() + g() * h()
. This is exactly the expression we looked at earlier. The answer will of course be 7. Now, naively you might assume that multiplication happens first, so it'll go there and it'll do g()
, then multiply it by h()
, then it'll do f()
and add it to the previous result.
Actually, compiling this with GCC 4.4.5 shows me that the functions are executed in the order that they appear in the expression: f()
, then g()
, then h()
. This isn't something that will necessarily happen the same in all compilers. It completely depends on how the compiler wants to do it.
If you're performing operations that are associative or commutative then the compiler is also free to swap around the mathematical groupings in the expression, but only if the result will be exactly the same. The compiler must be careful not to do any regroupings that may cause overflows to happen which wouldn't have happened anyway. As long as the result is as defined by the standard, the compiler is free to do what it likes.
精彩评论