views:

114

answers:

3

This is what i have coded today

#include <iostream>
using namespace std;

int function1()
{
  cout<<"hello from function1()"; return 0;
}

int function2()
{
  cout<<"hello from function2()"; return 0;
}

int main()
{
    int func_diffresult = 0;
    func_diffresult = function1() - function2();
    cout<<func_diffresult; /** prints 0 correctly **/
}

the output is get is hello from function2()hello from function1(). I think the output should be hello from function1()hello from function2(). Is my compiler playing with me?

+12  A: 

The order of evaluation of arguments of - operator is unspecified. So functions may be called in either order.

Prasoon Saurav
+4  A: 

The - operator effectively becomes operator-(function1(), function2()), and the order of evaluation of function parameters is deliberately unspecified.


Related notes:

One really good reason to leave it unspecified is to handle calling conventions efficiently. For example, the C calling convention requires parameters be pushed on the stack in reverse order.

Therefore, it makes sense to evaluate the functions in reverse order since the result may be pushed immediately. To evaluate parameters from left-to-right and then push the results from right-to-left involves storing all results before pushing any of them. If you really need to do this, you can do it manually. If it doesn't matter to you, the performance benefit probably does.

Zooba
That's true for `cdecl` on x86, but not all calling conventions push values onto the stack. Some of them pass arguments in registers.
dan04
Absolutely. That's why the order is "unspecified" rather than "right-to-left" (or "left-to-right") - and who knows what calling conventions will be used in the future? Better to say "don't rely on parameter order matching evaluation order" and let the compilers do it as efficiently as they can.
Zooba
+2  A: 

The ISO standards does not guarantee the order in which subexpressions will be evaluated.

From the c++0x draft standard:


1.9. Program execution:
     :
13/ Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread, which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [Note: The execution of unsequenced evaluations can overlap.]

Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first.]
     :
15/ Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
     :
When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function [Footnote: In other words, function executions do not interleave with each other]. [Note: Value computations and side effects associated with different argument expressions are unsequenced.]

Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.


In other words, the implementation is free to arrange the calls using whatever method it desires. However, function calls are treated specially as per the footnote - they do not interleave.

paxdiablo
Just curious: Does it mean that function1 and function2 can also be interleaved (and hence run parallely) on a multi CPU architecture?
Chubsdad
I guess so. Because the Standard term for either A before B, or B before A, but unspecified is 'indeterminately sequenced'. But since the Standard says 'Unsequenced', IMO, it means the function calls may be interleaved as well.
Chubsdad
@Chubsdad: yes, see the update (final sentence and note at end of first para of **13**, and entire second para of **13**). For unsequenced, they can overlap. For indeterminately sequenced, they're still sequenced (no overlap) but it could go AB or BA. The question relates to an unsequenced operation so it _could_ overlap.
paxdiablo
Nice answer: + 1
Chubsdad
Function calls can never be interleaved: "8/ Once the execution of a function begins, no expressions from the calling function are evaluated until execution of the called function has completed. (footnote: In other words, function executions do not "interleave" with each other)". Obviously, the as-if rule can be applied in some cases
dave
Good catch, @dave, I didn't see that one. Updated to fix.
paxdiablo
That makes the answer nicer
Chubsdad