Order of Evaluation in C++ Function Parameters

Parameter evaluation order before a function calling in C [duplicate]

No, function parameters are not evaluated in a defined order in C.

See Martin York's answers to What are all the common undefined behaviour that c++ programmer should know about?.

Order of evaluation in C++ function parameters

No, there's no such guarantee. It's unspecified according to the C++ standard.

Bjarne Stroustrup also says it explicitly in "The C++ Programming Language" 3rd edition section 6.2.2, with some reasoning:

Better code can be generated in the
absence of restrictions on expression
evaluation order

Although technically this refers to an earlier part of the same section which says that the order of evaluation of parts of an expression is also unspecified, i.e.

int x = f(2) + g(3);   // unspecified whether f() or g() is called first

function parameter evaluation order

C and C++ are two completely different languages; don't assume the same rules always apply to both. In the case of parameter evaluation order, however:

C99:

6.5.2.2 Function calls

...

10 The order of evaluation of the function designator, the actual arguments, and
subexpressions within the actual arguments is unspecified, but there is a sequence point
before the actual call.

[Edit]
C11 (draft):

6.5.2.2 Function calls

...

10 There is a sequence point after the evaluations of the function designator and the actual
arguments but before the actual call. 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.94)

...

94) In other words, function executions do not ‘‘interleave’’ with each other.

C++:

5.2.2 Function call

...

8 The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations take effect
before the function is entered. The order of evaluation of the postfix expression and the argument expression list is
unspecified.

Neither standard mandates the use of the hardware stack for passing function parameters; that's an implementation detail. The C++ standard uses the term "unwinding the stack" to describe calling destructors for automatically created objects on the path from a try block to a throw-expression, but that's it. Most popular architectures do pass parameters via a hardware stack, but it's not universal.

[Edit]

I am getting confusing information from the books.

This is not in the least surprising, since easily 90% of books written about C are simply crap.

While the language standard isn't a great resource for learning either C or C++, it's good to have handy for questions like this. The official™ standards documents cost real money, but there are drafts that are freely available online, and should be good enough for most purposes.

The latest C99 draft (with updates since original publication) is available here. The latest pre-publication C11 draft (which was officially ratified last year) is available here. And a publicly availble draft of the C++ language is available here, although it has an explicit disclaimer that some of the information is incomplete or incorrect.

Order of parameter evaluation of function call in GCC

If you are really asking foo(f1(), f2(), f3()) - which is more interesting than foo(1+2, 3+4, 5+6), since adding 1+2 and 3+4 won't have effect whether it is done first or last or in a random order.

Now, unfortunately, you can not rely on f1() and f2() and f3() being called in any particular order - as long as each function is called ONCE, it's fine for the order to be any order:

   f1, f2, f3
f1, f3, f2
f2, f3, f1
f2, f1, f3
f3, f2, f1
f3, f1, f2

(that covers all the permutations for three parameters).

It is entirely up to the compiler which it "thinks is best".

I wrote some code a long time back, and ran into this particular problem - I had something along the lines of:

char foo(char a, char b)
...
if (a =! 'x')
foo(fgetc(f), foo(fgetc(f)));
...

Since I expected the FIRST (left) fgetc() to be called first, and the second fgetc(), I could get the right behaviour. And it worked fine on the school computer. Then I took the code home and tried using it on my home computer. And for some reason it didn't work right. It took me quite some time to figure out that foo() was just being called infinitely, because a was never 'x', which stops the recursion - because 'x' would never appear in the second call.

That was using gcc on both machines, but one was a sparc (school computer) and the one at home was a x86 (386, running OS/2, that's how long ago).

The solution is to break it into several lines:

 char aa = fgetc(f);
char bb = fgetc(f);
foo(aa, foo(bb));

c function parameters order of evaluation

Isn't it guaranteed that if there's a function call as parameter, that function will be called first?

No, that is not guaranteed. The order of evaluation of actual parameters is not defined. The fact that one of your parameters is the result of evaluating a function call changes nothing. The other parameters could be evaluated before the function is called.

With your example:

printf("Input: %d. Output: %d.\nFunction called %d times.\n\n", n, 
fat(n, &count), count);

the call to printf is passed 4 parameters. These parameters can be evaluated in whatever order the compiler chooses.

C++ forcing function parameter evaluation order

The semi-colon that separates statements imposes a "happens before" relation.
auto && a = increment() must be evaluated first. It is guaranteed. The returned temporary will be bound to the reference a (and its lifetime extended) before the second call to increment.

There is no UB. This is the way to force an evaluation order.

The only gotcha here is if increment returned a reference itself, then you'd need to worry about lifetime issues. But if there was no lifetime issues, say if it returned a reference to count, there still would not be UB from the imposed evaluation of a and then b.

Compilers and argument order of evaluation in C++

It depends on the argument type, the called function's calling convention, the archtecture and the compiler. On an x86, the Pascal calling convention evaluates arguments left to right whereas in the C calling convention (__cdecl) it is right to left. Most programs which run on multiple platforms do take into account the calling conventions to skip surprises.

There is a nice article on Raymond Chen' blog if you are interested. You may also want to take a look at the Stack and Calling section of the GCC manual.

Edit: So long as we are splitting hairs: My answer treats this not as a language question but as a platform one. The language standard does not gurantee or prefer one over the other and leaves it as unspecified. Note the wording. It does not say this is undefined. Unspecified in this sense means something you cannot count on, non-portable behavior. I don't have the C spec/draft handy but it should be similar to that from my n2798 draft (C++)

Certain other aspects and operations of the abstract machine are described in this International Standard as unspecified (for example, order of evaluation of arguments to a function). Where possible, this International Standard defines a set of allowable behaviors. These define the nondeterministic aspects of the abstract machine. An instance of the abstract machine can thus have more than one possible execution sequence for a given program and a given input.

How not specify an exact order of evaluation of function argument helps C & C++ compiler to generate optimized code?

I think the whole premise of the question is wrong:

How not specify an exact order of evaluation of function argument helps C & C++ compiler to generate optimized code?

It is not about optimizing code (though it does allow that). It is about not penalizing compilers because the underlying hardware has certain ABI constraints.

Some systems depend on parameters being pushed to stack in reverse order while others depend on forward order. C++ runs on all kinds of systems with all kinds on constraints. If you enforce an order at the language level you will require some systems to pay a penalty to enforce that order.

The first rule of C++ is "If you don't use it then you should not have to pay for it". So enforcing an order would be a violation of the prime directive of C++.



Related Topics



Leave a reply



Submit