-3

Possible Duplicate: Undefined behavior and sequence points

 #include< iostream.h>
 int main()
 {
       int i=7,j=i;
       j=(i++,++i,j++*i);
       cout <<j;
       return 0;
 }

What will be the output of the C++ code?

It's my homework that my professor gave me.

Community
  • 1
  • 1
napster
  • 9
  • 4
  • 2
    Nothing will be, as there are no any std::out operations. – Draco Ater Nov 15 '10 at 18:04
  • 2
    Trick question — despite the inclusion of iostream.h, there's no output. Presumably you mean what would be the final values of i and j? – Tommy Nov 15 '10 at 18:05
  • 11
    Why is your professor still doing `#include `? Are you guys using Turbo C++? :p – wkl Nov 15 '10 at 18:05
  • 1
    sorry didnt write cout initially. Added it now. – napster Nov 15 '10 at 18:06
  • Also iostream.h has been "pre-standardisation" for > 10 years (http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.4) – Flexo Nov 15 '10 at 18:06
  • 2
    steve m how can it print yo mama. j is integer not a string. – napster Nov 15 '10 at 18:12
  • 2
    Yet more evidence that colleges are incapable of producing actual programmers. – John Dibling Nov 15 '10 at 18:12
  • 4
    Please double check if you've rewritten the code right. If so, then double-check if your professor is really qualified to teach C++ :). I hope it's a mistake. – Kos Nov 15 '10 at 18:13
  • 5
    In the real world, the correct answer is that the output of that code is an enraged programmer who will track down the author and give them an earful! – AshleysBrain Nov 15 '10 at 18:19
  • 2
    @napster - @Steve M forgot to add the 'humour' tag on his comment. The point that is being made here is that this is not an especially helpful C++ homework in the real world, because any programmer that wrote such code would be out of a job in short order. There **are** answers here that should help you understand it, as an academic exercise. See e.g. @Kos's response. – Steve Townsend Nov 15 '10 at 18:21
  • 5
    I thought Steve M was referring to the undefined behavior of the program, which allows his stated output to happen. But, shame to explain it ... :( – AshleysBrain Nov 15 '10 at 18:23
  • 9
    These questions are asked about twice a week. There's dozens of dupes for this. Fortunately we have now an FAQ entry for it: [Undefined Behavior and Sequence Points](http://stackoverflow.com/questions/4176328/faq-undefined-behavior-and-sequence-points). Read that very carefully. I bet it has more ammunition than your professor can take. – sbi Nov 15 '10 at 18:30

4 Answers4

10

It sometimes helps to convince people who don't believe this is undefined by actually compiling the program with several compilers and observing the results:

After fixing the iostream.h error,

  • g++ 4.5.2 prints 64
  • CLang++ 2.8 prints 63
  • Sun C++ 5.8 prints 63
  • MSVC 2010 prints 64

(oh, and, re-written to use C I/O, the original K&R C compiler on Unix 7 prints 63)

Cubbi
  • 46,567
  • 13
  • 103
  • 169
4

[Edited to account for OP's question changing edit]:

It's undefined as to what the output will be.

Paul Sonier
  • 38,903
  • 3
  • 77
  • 117
  • why and what are all of you saying undefined,? – napster Nov 15 '10 at 18:14
  • @napster: because the code sample as you gave it to has an undefined output. – Paul Sonier Nov 15 '10 at 18:19
  • 3
    @John there is no sequence point between `j++` and the modification of the assignment expression to `j`. Therefor, you get undefined behavior. You will need to rewrite it to `j=(i++,++i,j++,(j-1)*i);` to make this case defined. The "sequence point" FAQ entry needs more such examples, IMHO, and could spare on the mathematical aspects, like defining "partial order" and so on :) – Johannes Schaub - litb Nov 15 '10 at 18:23
  • 1
    @Johannes: I think that'll be defined in C++0x, but under the current standard, I don't think it is; there's still no sequence point between the assignment to `j` and the post-increment of j. The increment is sequenced relative to the computation of `(j-1)*i`, but *not* relative to the assignment to `j` (and the current standard does *not* require that assignment of a value happen after the value is computed). – Jerry Coffin Nov 15 '10 at 18:29
  • 1
    @Jerry well I agree this is vague, and I'm certainly not betting on anything. But there is some logic: In `a = (x, y)` you need to evaluate `(x, y)` before assigning. Evaluating that implies to evaluate `y`, and there is a sequence point between the evaluations of `x` and `y`, which implies that all side effects before evaluating `y` are complete. Therefor, there are no two side efffects between the same two sequence points: The assignment side effect will happen after the sequence point between x and y. – Johannes Schaub - litb Nov 15 '10 at 18:39
  • 1
    @litb, @Jerry: Correct, I wasn't looking widely enough -- only at the comma operators. This *is* undefined for the same reason why `j = j++` is undefined – John Dibling Nov 15 '10 at 18:41
  • I've deleted my comment to cut down on confusion – John Dibling Nov 15 '10 at 18:42
  • @Johannes: This has been argued (to death) previously: http://groups.google.com/group/alt.comp.lang.learn.c-c++/browse_frm/thread/81f62cab6b38e729/1eb3290468c4de56 Through C++03, I don't see any real reason to believe differently than I did then. – Jerry Coffin Nov 15 '10 at 19:00
  • @Jerry `(a=b)=c` is undefined in my opinion :) Here is my reasoning: Because there are two modifications to `a` between the same two sequence points. It's certainly true that the assignment in `a = b` must first be done before producing its lvalue result ("The result of the assignment operation is the value stored in the left operand after the assignment has taken place"): So we can say "the one assignment happens before the other", but that doesn't matter: We still have two assignments to `a` between the same two sequence points so behavior is still UB (as nonsensical as it may sound). – Johannes Schaub - litb Nov 15 '10 at 19:07
  • ... But that doesn't apply to `a = (0, a++, 0)`: Here, the two assignments will properly be spread across two sequence points. – Johannes Schaub - litb Nov 15 '10 at 19:12
  • @Johannes: Sorry. While that thread started out talking about(a=b)=c, it goes into quite a bit else as well, including quite a bit that's more relevant to the question at hand -- do you need to evaluate an expression before using its resulting value. – Jerry Coffin Nov 15 '10 at 19:27
  • The requirement "The result of the assignment operation is the value stored in the left operand after the assignment has taken place" has another important purpose: It makes `a = b = 0` defined behavior - the rule is that the *previous* vaue of `b` should only be used to determine the value to be stored in `b`. By saying that the lvalue refers to `b` after the assignment, the fetch of b's value will fetch b's *new* value. – Johannes Schaub - litb Nov 15 '10 at 19:40
  • I think as long as an implementation adheres to as-if, it can do any and everything. In the abstract machine, values stored in objects are only produced by evaluations, so if the implementation computes value a different way, it must take care not to yield other visible results. – Johannes Schaub - litb Nov 15 '10 at 19:42
3

There are the following errors in the code:

#include <iostream.h> should be #include <iostream>,

j is uninitialized so the value of j++*i isn't known - OK, this got fixed in the edit,

Besides, the assignment itself is improper. The convoluted line can be rewritten as:

i++;
++i;
j = j++ * i;

And the last part is invalid for the reasons described here:

Undefined behavior and sequence points

Community
  • 1
  • 1
Kos
  • 70,399
  • 25
  • 169
  • 233
  • 4
    Kudos for (accidentally?) achieving a double meaning with that comment :) – AshleysBrain Nov 15 '10 at 18:18
  • The rewrite of the assignment you have provided assigns an order to the operations that is not guaranteed. You probably intend that to be discovered in the reference link, but it should be noted explicitly. – gregg Nov 15 '10 at 18:19
  • @gregg, I believe you're mistaking the function calls with the comma operator - the comma has a well-defined order of execution and introduces a sequence point (see the reference link). – Kos Nov 15 '10 at 18:21
  • 1
    I still can't get why `j = j++` is undefined and `j = ++j` is well defined. :-/ – Šimon Tóth Nov 15 '10 at 18:21
  • @John Dibling - If I'm not mistaken, then there is a sequence point between `i++` and `++i`, then between `++i` and `j++ * i`, but NOT between `j++ * i` and `j=expression`, which introduces the UB - we have 2 independent writes to `j`. Phew, you got me confused there for a while. :) – Kos Nov 15 '10 at 18:23
  • @Let_Me_Be - in `j = ++j` you first increase `j`, then store the resulting value in `j`. In `j = ++j`, you have two writes "at the same time". – Kos Nov 15 '10 at 18:25
  • @Kos: Correct, see my comment in the other post(s) – John Dibling Nov 15 '10 at 18:42
  • And why exactly I got -2 here...? :) – Kos Nov 15 '10 at 19:54
-1

Essentially, you're incrementing i by 2, multiplying it by the original value of j, and adding one.

In the end, j=64

j = ((7+2)*7) + 1 = (9*7)+1 = 63+1 = 64

At least that's what my Visual Studio 2010 compiler does with it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
fbl
  • 2,840
  • 3
  • 33
  • 41
  • @flevine100: what makes you think something like this would be justified in the embedded community? – Jerry Coffin Nov 15 '10 at 18:26
  • It's probably not, but some of the embedded code I've seen is full of supposed 'space saving' optimizations. Personally, I would never write that code unless there was a justifiable reason that could not be ignored. – fbl Nov 15 '10 at 18:39
  • Just the examples of people who don't trust their compilers, I pressume. – Kos Nov 15 '10 at 18:47
  • 1
    -1 because 64 is wrong, the program invokes undefined behavior. – fredoverflow Nov 15 '10 at 18:50
  • To be fair, I specified that my VS2010 compiler produced it, but having reviewed the results on other compilers I now agree that 64 is only right in VS2010 and g++. – fbl Nov 15 '10 at 18:58