Reputation: 455
I know this is one of those "undefined behavior" questions, but a current cppreference page on the subject (as of C++23) itself gives two example's that I'm having trouble understanding from its rules on sequencing:
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
Namely, two questions for the two examples:
The C++ cppreference page given above gives one rule about the sequencing of function arguments that I can see as relevant here:
- In a function call, value computations and side effects of the initialization of every parameter are indeterminately sequenced with respect to value computations and side effects of any other parameter.
f(i = -2, i = -2);
not undefined? Did C++17 add language to specify that if the same result would occur regardless of order of evaluation of arguments, it's not undefined?f(++i, ++i);
as opposed to just simply not undefined?Upvotes: 0
Views: 110
Reputation: 141698
but the current C++ spec
This is not C++ spec. This is an amazing and great website called "cppreference". We usually work online with C++ standard draft https://eel.is/c++draft/ . The actual C++ standard has to be purchased https://www.iso.org/standard/79358.html .
why is f(i = -2, i = -2); not undefined?
Because it is indeterminately sequenced, as you quoted.
Did C++17 add language to specify that if the same result would occur regardless of order of evaluation of arguments, it's not undefined?
No. It added that function arguments are indeterminately sequenced. It was already there that when something is indeterminately sequenced it is not undefined behavior. And indeterminately sequenced may result in different result depending on the actual order of evaluation. The cppreference has:
Evaluations of A and B are indeterminately sequenced: they may be performed in any order but may not overlap: either A will be complete before B, or B will be complete before A. The order may be the opposite the next time the same expression is evaluated.
If evaluations are unsequenced, then it is undefined behavior. In cppreference:
If a side effect on a memory location is unsequenced relative to another side effect on the same memory location, the behavior is undefined.
What's different between these two examples to cause the "unspecified" for f(++i, ++i);
So in f(i = -2, i = -2);
whichever i = -2
will happen first, f(-2, -2)
will be called.
In f(++i, ++i)
it depends when ++
happens vs evaluating i
.. Starting with i = 0
, you can get f(1, 2)
, f(2, 1)
or f(2, 2)
- it is not specified which one.
Upvotes: 2
Reputation: 474266
i = -2
is the same expression with the same result value and side-effect: the result is -2, and the side effect is that i
will have the value -2. C++17 guarantees that one expression will fully complete before the other, but it doesn't guarantee which one goes first. But since they both have the same result and side-effect, the order doesn't matter.
++i
is the same expression. However, both the result of the expression and its side effects depend on the value of i
before that expression's evaluation. They also both change the value of i
; it's a read/modify/write. Therefore, which one goes first matters. One parameter will get one value, the other will get a value one larger than that. The standard does not specify which expression goes first (and you could get inconsistent results, such that it gets evaluated one way sometimes but the other way other times), but the result will be one way or the other.
Upvotes: 2