7
int i=2;
i = ++i + ++i + ++i;

Which is more correct? Java's result of 12 or C = 13. Or if not a matter of correctness, please elaborate.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Manny
  • 6,277
  • 3
  • 31
  • 45
  • 13
    That's odd; when I compile it in C my compiler dances like an undefined chicken. – Craig Gidney Oct 07 '10 at 06:27
  • 1
    why -1 ? Is this not a valid question? Anyhow @Strilanc, what compiler are you using? – Manny Oct 07 '10 at 06:28
  • 3
    If you *really* see that in your code, I think it's better to refactor that!! – Romain Linsolas Oct 07 '10 at 06:37
  • It is a trivial example because I just want to know how things work. – Manny Oct 07 '10 at 06:39
  • 3
    Duplicate of [How do we explain the result of the expression (++x)+(++x)+(++x)?](http://stackoverflow.com/questions/1525187/how-do-we-explain-the-result-of-the-expression-xxx) Why are these questions asked so often? – dalle Oct 07 '10 at 06:53
  • 2
    @dalle - not really, different languages will handle this differently. – Kobi Oct 07 '10 at 06:56
  • 1
    @dalle, that question doesn't even mention Java, which is quite different in this regard. – Matthew Flaschen Oct 07 '10 at 06:59
  • -1 from me, too, for asking a FAQ. Any book you'll ever read about these operators make it very clear that mixing multiple post/pre increment/decrement operators is undefined behaviour. – PP. Oct 07 '10 at 09:03
  • 1
    @dalle: I think that C's expression evaluation rules, in particular the sequence point rule, are genuinely surprising to many people at a certain stage of learning the language. Especially coming from Java, where it is all defined. So, a lot of people ask about it, and often (not this time) a few people give very wrong answers. As for why it's surprising - a little knowledge is a dangerous thing, so maybe people reach a fairly natural mental model of "how compilers do arithmetic" which simply doesn't take account of how C compilers *optimize* arithmetic, and so is wrong. – Steve Jessop Oct 07 '10 at 09:37
  • 1
    Also, even I find it slightly surprising that `++i + ++i` is undefined behavior, but is not a breach of language constraints. More to the point is that `int incboth(int *p, int *q) { return ++*p + ++*q; }` is fine if the caller passes in different values for p and q, and not fine if called with the same pointer value twice. Clearly the compiler cannot help you with that one (although C99 `restrict` at least indicates the intent), which is why the sequence point rule cannot be entirely expressed as a language constraint. – Steve Jessop Oct 07 '10 at 09:42
  • 1
    -1 for yet another repeat of the most frequent duplicate question. Can't SO implement some kind of duplicate warning when it sees too many ++'s close together or something? – R.. GitHub STOP HELPING ICE Oct 07 '10 at 16:45
  • @Steve Jessop: There's nothing stopping implementations from issuing warning messages. – David Thornley Oct 07 '10 at 16:46
  • 1
    @PP: Any book you read about C or C++ will point out that this is an error. The poster also asked about Java, which is an entirely different question. – David Thornley Oct 07 '10 at 16:48
  • Oh, and also: If you have to ask about the meaning of an expression on Stack Overflow or similar site, don't put it in a program. We don't want the next person working on your program to have to come here to understand your program. – David Thornley Oct 07 '10 at 16:51
  • @David: sure, but there's also nothing stopping compilers from issuing a warning for assigning to const, but that's a language constraint violation. I said I was only "slightly" surprised - I guess it's just unnecessarily complicated to define a reasonable constraint. – Steve Jessop Oct 07 '10 at 17:04
  • The question belongs closed. It's not a question about the Java behavior of this expression, but a question about why the C behavior does not match the Java behavior, and it's simply yet another case of being ignorant of sequence points like every other duplicate of this topic. – R.. GitHub STOP HELPING ICE Oct 07 '10 at 18:48
  • sorry for being ignorant – Manny Oct 08 '10 at 02:20

4 Answers4

28

Java guarantees (§15.7.1) that it will be evaluated left-to-right, giving 12. Specifically, ++ has higher precedence that +. So it first binds those, then it associates the addition operations left to right

i = (((++i) + (++i)) + (++i));

§15.7.1 says the left operand is evaluated first, and §15.7.2 says both operands are evaluated before the operation. So it evaluates like:

i = (((++i) + (++i)) + (++i));
i = ((3 + (++i)) + (++i)); // i = 3;
i = ((3 + 4) + (++i)); // i = 4;
i = (7 + (++i)); // i = 4;
i = (7 + 5); // i = 5;
i = 12;

In C, it is undefined behavior to modify a variable twice without a sequence point in between.

assylias
  • 321,522
  • 82
  • 660
  • 783
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • A small question - is left-to-right really needed here? In this example, can another order give a different result? I suppose it's more relevant to statements like `i = (i*=2) + (i*=3) + (i*=4);`, where order matters. – Kobi Oct 07 '10 at 06:53
  • @Kobi, not really, but I hope explaining simpler cases helps people work up to more complex ones. – Matthew Flaschen Oct 07 '10 at 07:01
  • 3
    Change it to `++i - ++i - ++i` and left-to-right order becomes very important. – PaulMcG Oct 07 '10 at 07:11
  • Shouldn't the step after `((3 + 4) + (++i))` be `((3 + 4) + 5)`? Since `++` has higher precedence than `+`? – configurator Oct 17 '10 at 23:17
  • @config, it's important to distinguish between precedence and order of evaluation. The precedence basically determines where the simulated parentheses are put; order of evaluation is the sequence of actual computations. Order of evaluation is in [§15.7](http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.7). Because of [§15.7.1](http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.7.1) the left operand `(3 + 4)` must be evaluated before the right operand `(++i)` (of the outer +). – Matthew Flaschen Oct 18 '10 at 04:44
18

There is nothing like more correct. It is actually undefined and its called Sequence Point Error. http://en.wikipedia.org/wiki/Sequence_point

Rohit
  • 525
  • 3
  • 8
5

The Java result makes sense to me because the operators give the result you would expect, but no serious program should contain a statement like this.

EDIT: I'm amused that this one sentence response has been my highest scored answer of the evening (compared to the dozen other answers I posted, some with pages of code samples). Such is life.

Tim M.
  • 53,671
  • 14
  • 120
  • 163
4

In C this is undefined behavior. There is no correct behavior.

Not a real meerkat
  • 5,604
  • 1
  • 24
  • 55
JoshD
  • 12,490
  • 3
  • 42
  • 53