Reputation: 97
What will be the order the function calls in the following expression:
a = f1(23, 14) * f2(12/4) + f3();
Does it depend on the compiler?
Upvotes: 3
Views: 1845
Reputation: 213711
Instead of just saying that this is unspecified, end of story, let me explain how this will be evaluated. Most importantly, don't mix up the concept of order of evaluation (of operands) with the concept of operator precedence, they are different things.
The order in which the whole expression itself is evaluated is easy to understand in this case, when we only have the basic math operators. But it can be less trivial when other C operators are involved. Therefore, always start evaluating an expression by finding out what order the sub expressions will be evaluated:
The operator precedence rules are guaranteed to be the same for every compiler. They state that the binary multiplication operator (*) has higher priority than the binary addition operator (+). Both of them have higher priority than the assignment operator (=). So it is guaranteed that the sub expression f1(23, 14) * f2(12/4)
will be evaluated first, then the result of that will become an operand of the addition with f3()
and finally the result will be assigned to a
.
To illustrate this, the expression is equal to a = ( (f1(23, 14) * f2(12/4)) + f3() );
.
So we have the sub expression f1(23, 14) * f2(12/4)
. The order of evaluation in which the operands themselves are evaluated is unspecified behavior, meaning that we cannot know whether the f1 or the f2 operand is evaluated first. The compiler is free to evaluate them either left-to-right or right-to-left, and does not need to document which way that applies. All we know is that the compiler will consistently evaluate either left-to-right or right-to-left.
Let us assume that the particular compiler evaluates left-to-right. f1(23, 14)
will then be evaluated first. The next question then, is which of the parameters to the function that will be evaluated first. Same thing applies here, the order of evaluation of function parameters is also unspecified. In this case it doesn't matter, as both parameters are integer constants.
With left-to-right order of evaluation, the compiler will evaluate (and execute) f1 first, then f2, then multiply their results and store it in a temporary, invisible variable. It will then evaluate f3, and then perform the addition and finally assign the result to a
.
The important lesson learned here is: since the order of evaluation of sub-expressions is unspecified, each sub-expression should not contain any side effects that depends on the order of evaluation. In this example, if f1 and f2 had both written the numbers 1 or 2 respectively to a global variable, that global variable would have the value 2 in the end if the compiler evalutes left-to-right, but 1 if it evaluates right-to-left. Such code will work perfectly on one compiler, but crash miserably on another.
Upvotes: 0
Reputation: 11787
The order can't be predicted in this case. It's not compiler dependent, it's unspecified; even with same compiler you can get different orders of evaluation.
Upvotes: 3
Reputation: 206518
It is Unspecified in both C and C++.
References:
C++03 Standard:Section 5: Expressions, Para 4:
except where noted [e.g. special rules for && and ||], the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is Unspecified.
C99 Standard:Section 6.5:
The grouping of operators and operands is indicated by the syntax.72) 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.
Upvotes: 6
Reputation: 361362
Order of evaluation of each operand is unspecified in C and C++, which means, in your case, the order of function calling is unspecified as per the Standards.
Note that it is unspecified, not implementation-defined.
Upvotes: 12
Reputation: 258578
C++ : The standard guarantees that all expressions encountered before a sequence point are evaluated before that sequence point is reached. In your case, there is no sequence point between =
and ;
, so the order is unspecified.
Upvotes: 4