46

I have a single line code,

int a = 10;
a = ++a * ( ++a + 5);

My expected output was 12 * (11 + 5) = 192 ,but I got 187. As much as I knew the increment operator inside () is to be solved first, then why the one outside is solved first?

frunkad
  • 2,433
  • 1
  • 23
  • 35
  • 16
    Just to be clear, this should be an academic exercise and not production code. Regardless of whether any particular language has well-defined semantics, this is unclear and confusing and should be avoided. Use those sequence points! –  Jan 29 '15 at 16:38
  • 59
    The idea that the *entire thing in parentheses* is evaluated first is simply false, so stop believing that. When you parenthesize an expression, that *operator* will run first. So if you have `A() * ( B() + C() )` then the *addition* happens before the *multiplication*, but that doesn't mean that the call to `B()` happens before the call to `A()`. It happens after. The order here is `A()`, then `B()`, then `C()`, then the addition, then the multiplication. See, the parentheses made the addition happen before the multiplication. – Eric Lippert Jan 29 '15 at 17:45
  • read about [sequence point](https://en.wikipedia.org/wiki/Sequence_point) – phuclv Jan 29 '15 at 19:23
  • 20
    Why are people linking to C++ questions on sequence points for a Java question?! – MSalters Jan 29 '15 at 19:51
  • 2
    @MSalters Someone defaced the question. I edited it back. (Sorry for the edit followed by rollback. That should have just been a rollback.) – David Schwartz Jan 29 '15 at 22:20
  • 5
    @tbodt Please don't change the whole meaning of someone else's question. The answers for C++ and C are totally different from the answers for Java. – David Schwartz Jan 29 '15 at 22:23
  • 8
    @tbodt: Because the way the languages are defined is different. Java gives much stronger guarantees about what order expressions will be evaluated in... – psmears Jan 29 '15 at 22:30
  • 7
    @tbodt Because the OP wants the answer to the question they asked, not the totally different answers to the question you think he should have asked. With your tag change, answers will be about sequence points and undefined behavior, which has no relevance to the question the OP actually asked. – David Schwartz Jan 29 '15 at 22:42
  • Removed C / C++ tags. In those languages, the code in the question invokes undefined behavior (and so the rest of the question is meaning less). See [undefined behavior and sequence points](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points). – Synxis Jan 29 '15 at 22:46
  • @MSalters probably because they didn't read the question carefully, and *almost all* questions with two `++` operators in one statement are about C/C++ sequence points. – user253751 Jan 30 '15 at 00:23
  • Although some details of the answer are Java-specific, the general rule that parentheses only affect grouping, not order, is very close to language-agnostic. – Barmar Feb 03 '15 at 19:34

5 Answers5

101

Expressions are evaluated left to right. Parentheses (and precedence) just express grouping, they don't express ordering of evaluation.

So

 11 * (12 + 5)
++a   ++a

equals

187
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
30

Quoting from Eric Lippert's Blog:

The evaluation of an arithmetical expression is controlled by three sets of rules: precedence rules, associativity rules, and order rules.

Precedence rules describe how an underparenthesized expression should be parenthesized when the expression mixes different kinds of operators.

Associativity rules describe how an underparenthesized expression should be parenthesized when the expression has a bunch of the same kind of operator.

Order of evaluation rules describe the order in which each operand in an expression is evaluated.

Higher precedence results in grouping of operands with an operator and doesn't mean the evaluation of operands. It is the order of evaluation which decides sequence of evaluation of sub-expressions in an expression.


Update:

As I can see many programmers think that statement

a = ++a * ( ++a + 5);  

will invoke undefined behavior. Yes it will invoke UB if there is no guarantee of evaluation order of operands of an operator.

But this is not true in context of java programming language. It has well defined behavior in java (as well as in C#). The Java Language Specification states that:

15.7. Evaluation Order

The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.

Example 15.7.1-1. Left-Hand Operand Is Evaluated First

In the following program, the * operator has a left-hand operand that contains an assignment to a variable and a right-hand operand that contains a reference to the same variable. The value produced by the reference will reflect the fact that the assignment occurred first.

class Test1 {
    public static void main(String[] args) {
        int i = 2;
        int j = (i=3) * i;
        System.out.println(j);
    }
}

This program produces the output:

9

It is not permitted for evaluation of the * operator to produce 6 instead of 9.

But, still java specification clearly states that not to write such codes:

It is recommended that code not rely crucially on this specification. Code is usually clearer when each expression contains at most one side effect, as its outermost operation, and when code does not depend on exactly which exception arises as a consequence of the left-to-right evaluation of expressions.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • 9
    Thanks for the shout-out. I note that the blog article is talking about C#, but in this case the rules in C# and Java are the same. – Eric Lippert Jan 29 '15 at 17:47
  • 1
    @EricLippert; Yes. I know. It is talking about C# but definition you provided there for *precedence*, *associativity* and *order of evaluation* fits for any programming language, AFAIK. – haccks Jan 29 '15 at 17:54
  • 6
    @haccks: These kind of rules are particular to languages with infix operators. Languages with purely postfix or purely prefix operators do not need them. `2 3 4 + *` unambiguously is (3+4) * 2 = 14. – MSalters Jan 29 '15 at 19:54
11

From that snippet

int a = 10;
a = ++a * ( ++a + 5);

Sometimes, the most simple solution is to use javap to understand the evaluation order:

 0: bipush 10 // push 10 onto the stack (stack={10})
 2: istore_1  // store 10 into variable 1 (a = 10, stack={})
 3: iinc 1, 1 // increment local variable 1 by 1 (a = 11, stack={})
 6: iload_1   // push integer in local variable 1 onto the stack (a = 11, stack = {11})
 7: iinc 1, 1 // increment local variable 1 by 1 (a = 12, stack={11})
 10: iload_1  // push integer in local variable 1 onto the stack (a = 12, stack = {12, 11})
 11: iconst_5 // load the int value 5 onto the stack (a = 12, stack = {5, 12, 11})
 12: iadd     // add 5 and 12 (a = 12, stack = {17, 11})
 13: imul     // multiply 17 and 11 (a = 12, stack = {})
  1. a is incremented by 1. (line 3) // a = 11
  2. a is incremented by 1. (line 7) // a = 12
  3. add 5 to a (line 12) // a = 17
  4. multiply 11 to 17 (line 13) // a = 187

(10 + 1 + 1 + 5) * 11 = 187

Pier-Alexandre Bouchard
  • 5,135
  • 5
  • 37
  • 72
2

The effect of parentheses is to control which computed values are used as operands for subsequent operations. They control the sequence in which operations are performed only to the extent that an operation cannot be evaluated until after its operands have been. Consider the expressions:

(a()+b()) * (c()+d())
a() + (b()*c()) + d()

The parenthesis need not (and in Java cannot) affect the order in which a(), b(), c(), and d() are called. They may affect whether the multiplication gets performed before or after d() gets called, but only in very rare circumstances (e.g. d() calling a Java Native Interface which alters the numerical rounding mode used in multiplication in a way Java doesn't know about) would code have any way of knowing or caring whether the multiply was performed before or after d().

Otherwise, what's important is that in the first case, one addition operations will act upon a() and b(), and the other upon c() and d(); the multiplication will act upon a()+b() and c()+d(). In the other case, the first multiplication will act upon b() and c(), the first addition upon a() and the aforementioned product, and the second addition upon the first sum and d().

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Hi @supercat. The brackets are said to take precedence over the ++ (and --) operators. What is the meaning of this if we initially work from left to right doing our post-increments through the entire expression, *then* start to take brackets into account for the subsequent order of operations? Does this not mean that the post-increment and post-decrement operators take precedence over any operations in brackets as we must do the former first? Still confused over this! Thanks. – Zippy Oct 26 '17 at 20:29
  • @Zippy: Java's `++` and `--` operators are only meaningful for variables of primitive type or for subscripted arrays of primitives. In an expression like `++x[a()+b()];` the increment cannot occur until after the calls to both `a()` and `b()` have been processed; an arbitrary number of functions could be forced to execute before the increment by enclosing them in the brackets. I don't think any similar situation can occur in Java with parentheses, however, since operators like `+`, `-`, `*`, etc. all yield things which cannot be acted upon with `++`, `--`, nor `.`. – supercat Oct 26 '17 at 20:39
-1
  int a = 10;
  a = ++a * ( ++a + 5);

above kind of expressions are always evaluated in left to right fashion be it C or JAVA

in this case it is solving like this 11*(12+5) which results in 11*17 = 187 // w.r.t java

but if it we solve the same expression w.r.t C-language

then the answer gets changed as the way of evaluation changes

in c first pre-increment/pre-decrement happens ,so if "N" no of times pre inc/dec are there in the expression then inc/dec will happen first "N" no of times

then the same value will be substituted in each ocurrence of the variable in the expression and the expression value is calculated and after that post increment/decrement happens

i.e a gets incremented to 11 then again 12 as there are two incrementation for a in the expression and then the expression is evaluated as

12*(12+5)=12*17=204 //w.r.t C-language

  • Order of evaluation is not necessarily left to right in C. Everything. You've written about C here is irrelevant to the question and should be deleted. – user207421 Dec 20 '15 at 01:25