Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Evaluation order of function arguments and default arguments

Tags:

I recently ran across the following situation:

#include <iostream>

int *p = 0;

int f() {
    p = new int(10);
    return 0;
}

void g(int x, int *y = p) {
    std::cout << y << std::endl;
}

int main() {
    g(f());
}

This is quite subtle, since you usually don't expect the default arguments to change during their evaluation for the function call. I had to take a look at the assembly to spot this error.

Now my question is: Is this really undefined behavior, since there aren't any guarantees concerning the evaluation order of function arguments?

like image 730
phlipsy Avatar asked Aug 26 '15 09:08

phlipsy


People also ask

Does the order of arguments in a function matter?

Yes, it matters. The arguments must be given in the order the function expects them. C passes arguments by value. It has no way of associating a value with an argument other than by position.

What is the evaluation order of the function parameters in C++?

The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in a default argument, even if they are not evaluated. The same verbiage is used by C++14 standard as well, and is found under the same section.

When calling a function the arguments should be in order?

3. Positional Arguments. During a function call, values passed through arguments should be in the order of parameters in the function definition. This is called positional arguments.

What is an evaluation order?

Order of evaluation refers to the operator precedence and associativity rules according to which mathematical expressions are evaluated.


1 Answers

The order of evaluation (i.e. determining the value) of function arguments is not specified. The compiler is free to execute them in any order, and even intermingled if there are no other factors stopping it from doing so.

Evaluation of default arguments happens in the context of the caller, not the callee. So the call to f() is necessary for one argument, and reading the global variable p for the other. Which order this happens in is not specified, so the global could be read before or after the call to f().

like image 85
Sebastian Redl Avatar answered Sep 21 '22 18:09

Sebastian Redl