5

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 2
    One of the things that can happen if you cross the street without looking both ways is that you make it to the other side safely. But it's an error to *predict* that a person who crosses the street without looking both ways will make it to the other side safely. – David Schwartz Sep 30 '15 at 08:45
  • Similar to [Sequence Point ambiguity, undefined behavior?](http://stackoverflow.com/q/29513572/1708801) – Shafik Yaghmour Sep 30 '15 at 09:34

2 Answers2

14
   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.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • 5
    @user4791206 What do you mean by "works fine"? Since you cannot predict what it will do, why would you say what it happened to do is it working fine? Someone who predicted it would evaluate in the other order wouldn't say it worked fine, would they? – David Schwartz Sep 30 '15 at 08:53
  • Means , problem of evaluation order is undefined behavior [I-read](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) ? –  Sep 30 '15 at 09:10
  • 2
    It''s hard to say precisely what category this falls into because you've given the question three different language tags. It's either undefined or unspecified. You can check the specification for the particular language you're interested in. – David Schwartz Sep 30 '15 at 09:13
  • but the question doesn't mention anything ? –  Sep 30 '15 at 09:15
  • Well, the answer is the same whether it's undefined or unspecified -- we cannot predict that any of those answers will result. – David Schwartz Sep 30 '15 at 09:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/90969/discussion-between-user4791206-and-david-schwartz). –  Sep 30 '15 at 09:30
9

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 2
    As a side note, the same text is different in C++11 but has the very same meaning. I think C++11 (and C11) only made the text much harder to understand, why I am quoting an older version of the standard. – Lundin Sep 30 '15 at 09:23
  • In general "unspecified behavior" doesn't mean that a programmer can't know what the code will do--merely that the programmer can't know in any given case which of the possible behaviors a compiler will select. If all possible combinations of compiler behavior would meet the programmer's requirements, then a programmer would be entitled to expect the program to work correctly. There is nothing wrong with code relying upon a compiler choosing in unspecified fashion from among defined actions, as long as it will work with any such selection the compiler happens to make. – supercat May 16 '16 at 19:45