Why Is the Order of Evaluation for Function Parameters Unspecified in C++

Parameter evaluation order before a function calling in C

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

Explain the order of evaluation in printf

The order in which the parameters to a function are passed is not defined in the standard, and is determined by the calling convention used by the compiler.
I think in your case, cdecl calling convention (which many C compilers use for x86 architecture) is used in which arguments in a function get evaluated from right to left.

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.

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++.

In a C function call, in which order are the parameters passed/evaluated?

Evaluation of function calls is specified in the 2018 version of the C standard clause 6.5.2.2, but this clause does not specify the order of evaluation of the arguments. Any order is permitted.

As a consequence of this, the behavior of print(++ptr, ptr--, ptr, ptr++, ++ptr); is not defined by the C standard. 6.5 2 says:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

ptr is a scalar object. (C 2018 6.2.5 21 says “Arithmetic types and pointer types are collectively called scalar types.”) ++ptr and ptr-- change ptr by a side effect. (The “main” effect of ++ptr is to evaluate to the incremented value of ptr. Its side effect is to update the stored value of ptr.) Since there is no ordering imposed on these side effects, the conditions of 6.5 2 are satisfied, so it applies, and the behavior is not defined by the C standard.

Note that this does not just mean that ptr may be updated in whatever order the compiler happens to choose. When the C standard says behavior is undefined, that means it does not impose any requirements on the behavior at all. Two updates to the object might conflict, updating different bytes of it in different orders, producing a value that is impossible to obtain by separate consecutive updates in any order. (This could happen, for example, when a compiler implements four-byte pointers using two-byte updates in a primitive machine.) Or the optimizer in the compiler could recognize the code does not have defined behavior and remove it completely from the program or replace it by other code. (For example, if the program contains a branch between two sequences of code, and the optimizer recognizes one branch would have undefined behavior in a particular circumstances, it can omit the code that evaluates the choice and use only the code on the other branch.)

Why doesn't c++ have a specified order for evaluating function arguements?

Why doesn't C++ do it this way?

For starters, C++ isn't a functional programming language.

And the fastest way to evaluate the arguments depends on the implementation and architecture, so the compiler gets to choose. We don't pay for what we don't use, in C++, so if you need to specify an evaluation order yourself then you can do so explicitly with named variables.

Although, continuing the theme of newer standards leaving behind sacred C++ paradigms, C++17 will sadly add some evaluation order guarantees, ruining all of that.



Related Topics



Leave a reply



Submit