phlipsy
phlipsy

Reputation: 2949

Evaluation order of function arguments and default arguments

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?

Upvotes: 20

Views: 1866

Answers (2)

CiaPan
CiaPan

Reputation: 9570

If I understand it correctly, your call

    g(f());

is equivalent to

    g(f(), p);

due to the declaration

    void g(int x, int *y = p);

And arguments to the g function , f() and p, can be evaluated in any order, so you can get g called with y assigned either zero (if p is evaluated first, then it returns its initial value) or the newly allocated array pointer (if f() is evaluated first and it assigns a new value to p as its side effect).

Upvotes: 14

Sebastian Redl
Sebastian Redl

Reputation: 72215

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().

Upvotes: 15

Related Questions