I thought I understand how sequence points work in C++, but this GeeksQuiz question puzzled me:
int f(int &x, int c) {
c = c - 1;
if (c == 0) return 1;
x = x + 1;
return f(x, c) * x;
}
int main() {
int p = 5;
cout << f(p, p) << endl;
return 0;
}
The “correct” answer to this question says it prints 6561. Indeed, in VS2013 it does. But isn't it UB anyway because there is no guarantee which will be evaluated first: f(x, c)
or x
. We get 6561 if f(x, c)
is evaluated first: the whole thing turns into five recursive calls: the first four (c = 5, 4, 3, 2
) continue on, the last one (c = 1) terminates and returns 1, which amounts to 9 ** 4
in the end.
However, if x
was evaluated first, then we'd get 6 * 7 * 8 * 9 * 1
instead. The funny thing is, in VS2013 even replacing f(x, c) * x
with x * f(x, c)
doesn't change the result. Not that it means anything.
According to the standard, is this UB or not? If not, why?
In C and more generally in computer science, a function or expression is said to have a side effect if it modifies a state outside its scope or has an observable interaction with its calling functions or the outside world.
Now, whenever a function is called a new stack frame is created with all the function's data and this stack frame is pushed in the program stack, and the stack pointer that always points the top of the program stack points the stack frame pushed as it is on the top of the program stack.
A function call is an expression containing the function name followed by the function call operator, () . If the function has been defined to receive parameters, the values that are to be sent into the function are listed inside the parentheses of the function call operator.
In some people, vitamin C might cause side effects such as stomach cramps, nausea, heartburn, and headache. The chance of getting these side effects increases with higher doses. Taking more than 2000 mg daily is possibly unsafe and may cause kidney stones and severe diarrhea.
This is UB.
n4140 §1.9 [intro.execution]/15
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [...] If a side effect on a scalar object is unsequenced relative to [...] value computation using the value of the same scalar object [...] the behavior is undefined.
Multiplicative operators don't have sequencing explicitly noted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With