12
x = 1;
std::cout << ((++x)+(++x)+(++x));

I expect the output to be 11, but it's actually 12. Why?

klutt
  • 30,332
  • 17
  • 55
  • 95
Rohit Banga
  • 18,458
  • 31
  • 113
  • 191
  • 23
    I would expect it to be 9... :/ –  Oct 06 '09 at 12:09
  • 1
    @Charlie: Some kompilers might do that :) – Artelius Oct 06 '09 at 12:21
  • 33
    I would expect a goat sacrifice before relying on code like that. – György Andrasek Oct 06 '09 at 12:21
  • @Jurily wanted to know the behaviour of the compiler – Rohit Banga Oct 06 '09 at 12:26
  • 2
    I still would like to hear why you would expect the result to be 11... – Ed S. Nov 22 '09 at 01:34
  • Interesting. Just tried it down in the JavaScript console. Answer is 9 in Chrome. – Nosredna Nov 22 '09 at 01:35
  • 1
    @Nosredna: You are aware that this question is about the behavior of this code snippet in C++, not Javascript, right? In the language I just invented, `(++x)+(++x)+(++x)` makes the computer eject the DVD tray. But since it's not C++, it's not relevant to this question. ;) – jalf Nov 22 '09 at 02:13
  • 2
    I commented mostly because Charlie Somerville was expecting 9. It's pretty clearly been established in the answers that the result is undefined in C++. So now I'm wondering what other C-syntax derived languages do. – Nosredna Nov 22 '09 at 02:38

5 Answers5

65

We explain it by expecting undefined behaviour rather than any particular result. As the expression attempts to modify x multiple times without an intervening sequence point its behaviour is undefined.

Dustin Getz
  • 21,282
  • 15
  • 82
  • 131
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    +1 I just tried this using gcc 3.2.2 on Linux, and the expression returns 10 (9 and 12 eat your heart out...) – Todd Owen Oct 06 '09 at 12:23
  • Here is an imho nice sequence point description in the GCC manual: http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Warning-Options.html#index-Wsequence_002dpoint-278 – Johannes Schaub - litb Oct 06 '09 at 13:20
  • 4
    Then why isn't it a syntax error? Anything ambiguous that makes it into compiled code...seems like an oversight. – Alex Feinman Oct 06 '09 at 13:34
  • @Alex Feinman: forcing conforming implementations to diagnose an error adds an extra burden to implementers. Whether this cost outweighs the benefit for users is a judgement call. Often the C++ standard comes down on the side of not burdening implementers unnecessarily. Given the complexity of writing a C++ implementation this may be no bad thing. – CB Bailey Oct 06 '09 at 13:49
  • @Alex Feinman: That's like asking why this isn't a syntax error: "MyClass& ptr = NULL; ptr->doSomething();" Because no one who knows better will write that. – Bill Oct 06 '09 at 14:25
  • 3
    @Bill: it's not really like asking that, since your example requires DFA to analyse, whereas "multiple sub-expressions of an expression which modify the same variable and are not separated in the full expression by a sequence point" is at least theoretically diagnosable just by local analysis of the expression. But the way the C++ standard expresses the rule is "any allowable execution order of the expression" has no sequence-point separator, and implementations are quite reasonably not expected to reason about all legal execution orders. – Steve Jessop Oct 06 '09 at 15:15
  • ...and in any case even though this example with repeated use of `x` is not actually that hard to diagnose, if there could be aliases involved in the expression then it would be. Often half a job of catching errors is worse than none at all, since it encourages people to mistakenly think they don't have to think about that class of error because the compiler will do it for them. – Steve Jessop Oct 06 '09 at 15:18
12

As others have said, the C and C++ standards do not define the behaviour that this will produce.

But for those people who don't see why the standards would do such a thing, let's go through a "real world" example:

1 * 2 + 3 + 4 * 5

There's nothing wrong with calculating 1 * 2 + 3 before we calculate 4*5. Just because multiplication has a higher precedence than addition doesn't mean we need to perform all multiplication in the expression before doing any addition. In fact there are many different orders you validly could perform your calculations.

Where evaluations have side effects, different evaluation orders can affect the result. If the standard does not define the behaviour, do not rely on it.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
Artelius
  • 48,337
  • 13
  • 89
  • 105
  • then what is the use of operator precedence. i don't understand your example: 1*2 + 3 + 4 * 5 = (1*2) + 3 + (4*5) no? – Rohit Banga Oct 06 '09 at 12:46
  • or a simpler example: 1*2+3*4= (1*2)+(3*4) – Rohit Banga Oct 06 '09 at 12:47
  • 2
    (1*2+3) + (4+5) == (1*2) + (3+4*5). there is more than exactly one way to sequence the execution, such that order of operations is still preserved. math is stateless, but if an operation affects state, you have to specify the sequence of execution more specifically. – Dustin Getz Oct 06 '09 at 12:52
  • 2
    @Dustin Getz: Technically, C++ grammar specifies that the expression must be (((1*2) + 3) + (4*5)) and not ((1*2) + (3 + (4*5))) but you are right that the calculation order could be 1*2, 4*5, (1*2)+3, ((1*2) + 3) + (4*5) or 1*2, (1*2) + 3, 4*5, ((1*2) + 3) + (4*5) or a number of other possibilities including independent parts being done in parallel. – CB Bailey Oct 06 '09 at 13:10
4

This is actually undefined. C++ doesn't define explicitly the order of execution of a statement so it depends on the compiler and this syntax shouldn't be used.

Julien Lebosquain
  • 40,639
  • 8
  • 105
  • 117
  • 1
    It's actually worse than just the order of execution being unspecified (which would just mean you don't know what the answer will be), in this case the behavior is undefined (so you don't know whether your computer will catch fire). – Steve Jessop Oct 06 '09 at 15:22
3

The code snippet will invoke Undefined behavior in both C/C++.Read about Sequence Point from here.

whacko__Cracko
  • 6,592
  • 8
  • 33
  • 35
-1

In my opinion

cout<<((++x)+(++x)+(++x));

compiler first run prefix ++x so value of x becomes

x=2


now by ++x, x will become

x=3


after ++x

x=4


Now its time to add values of x

x+x+x=4+4+4

x+x+x=12

  • Opinions are not answers. It is also in contradiction with what is already marked as the correct answer: undefined – Jan Doggen Feb 23 '15 at 14:44
  • I only told that above expression does not mean 2+3+4 because value of x is changed first then it is added. means 2+3+4 is not answer but it actually add like this 4+4+4. – Mohsin Ammar Feb 23 '15 at 17:44
  • Though the other answers might be technically appropriate in a general sense, this is the only answer that actually explains why 12 is a logical result. So +1 for explaining that, even if this is a weird pattern that shouldn't be followed in practice. In my eyes, this in conjunction with the other answers is what's really required to completely answer the original question. Explaining why this isn't the only way it could be interpreted would also be a nice addition to lead into the undefined behavior aspect. – thesquaregroot Mar 21 '18 at 12:34