user4791206
user4791206

Reputation:

Is undefined behavior in given code?

What is the return value of f(p,p), if the value of p is initialized to 5 before the call? Note that the first parameter is passed by reference, whereas the second parameter is passed by value.

int f (int &x, int c) {
       c = c - 1;
       if (c==0) return 1;
       x = x + 1;
       return f(x,c) * x;
}

Options are:

  1. 3024
  2. 6561
  3. 55440
  4. 161051

I try to explain:


In this code, there will be four recursive calls with parameters (6,4), (7,3), (8,2) and (9,1). The last call returns 1. But due to pass by reference, x in all the previous functions is now 9. Hence, the value returned by f(p,p) will be 9 * 9 * 9 * 9 * 1 = 6561.


This question is from the competitive exam GATE, (see Q.no.-42). The answer key is given by GATE "Marks to all" (means there is no option correct.) key set-C, Q.no.-42. Somewhere explained as:

In GATE 2013 marks were given to all as the same code in C/C++ produces undefined behavior. This is because * is not a sequence point in C/C++. The correct code must replace

return f(x,c) * x;

with

 res = f(x,c);
 return res * x;

But the given code works fine. Is GATE's key wrong? Or is really the mistake with the question?

Upvotes: 5

Views: 375

Answers (2)

Lundin
Lundin

Reputation: 213276

C++03 chapter 5:

Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.

So in the case of f(x,c) * x, the order of evaluation of the operands is unspecified, meaning that you can't know if the left or right operand will get evaluated first.

Your code has unspecified behavior, meaning that it will behave in a certain defined manner which is only known to the compiler. The programmer can't know what the code will do, only that it will either evaluate the left operand first, or the right operand first. The compiler is even allowed to change the order of evaluation on a case-to-case basis, for optimization purposes.

If the order of evaluation matters, you need to rewrite the code. Code relying on unspecified behavior is always a bug, possibly a quite subtle one which will not immediately surface.

Unspecified behavior is different from undefined behavior, which would mean that anything could happen, including the program going haywire or crashing.

Upvotes: 9

David Schwartz
David Schwartz

Reputation: 182743

   return f(x,c) * x;

The result of this operation depends on the order in which the two things are evaluated. Since you cannot predict the order they'll be evaluated, you cannot predict the result of this operation.

Upvotes: 14

Related Questions