6

A bit confused

I have a code and it is giving different answers in different language and compilers
the code is

Int a=4
Int b = ++a + a++ + --a

Please ignore the syntactical errors
But this logic give different answers in different compiler and language like in
C(turbo c++ compiler) it gives 12
C(gcc)- 16
Java- 15
Python- 12

Can anybody explain the logic behind this...

Comments
  • 5
    If I remember my C++ operations correctly, the second line should expand to:
    int b = (4+1) + 5 + (5 - 1) + 1 = 15.

    So Java is doing it correctly.

    Python doesn't actually use those operators, so you're just negating a twice before adding it and double-evaluating a to the same sign for two operations, so you just add a three times and get 12. (+ and - are merely unary operators in python.)

    Apparently both C and C++ leave modifying an object between two sequence points as undefined. (That is, if you modify a multiple times in the same statement as you are doing, it's up to the compiler to decide what to do.) So Turbo C++ does it one way and GCC does it another way and because they're not using the same orderings behind the scenes, they get different results. Turbo C++ seems to just not do anything (the same as Python, in this case), and GCC treats each operation as prefix (probably so it can guarantee a result that its internals hasn't mangled somewhere.)

    I didn't know this either.
  • 3
    @powerfulparadox actually turboc++ is also doing the operation as
    According to What I have studied it is doing like this
    The expression is like
    B= ++a + a++ + - - a
    So it is first preincrementing I. E. 4 becomes 5
    Then it is postincrementing I. E. a is still 5 (till the execution completes)
    Then it is predecrementing I. E. a become 4
    Then it adds the three 4

    I am sure with this concept because when I do ++a alone it is working the correct that means it is giving 5 as output
  • 3
    I suppose when I said "Java is doing it correctly" I should have said "Java performs the expected calculations" because all of them are technically doing correct things, just unexpected ones for everyone else.
  • 0
    @ankitbansal Again, modifying an object multiple times before the compiler must guarantee a result (i. e. the end of a statement) is undefined. And I'm not sure what you mean when you have at some values evaluated to 5 and then "it adds the three 4s."

    When you do either pre- or post-increment (or decrements) by themselves you will get an expected result because the behavior is defined. It's when you try them multiple times (or even something as simple as a++ + 1) that the compiler cannot be relied on to do what you expect, which is proved by the result being different than what Java gives.
  • 0
    Logic behind this is that compilers optimise stuff and evaluate things in different order.

    C/C++ theoretically does right-to-left if it were e.g. passing parameters to the function. But this is addition. So which order is correct? Probably neither, because of those optimisations. Check different optimisation parameters in gcc.

    Java looks like doing the normal addition left-to-right. (pre-incr) 5 + 5 (here post-incr to 6) + (pre-decr) 5

    Python doesn't have ++ and -- because of syntactical ambiguity and that problem with what comes first. -- is double unary minus, so it doesn't change the value. + is unary as well. So you just do a+a+a there.
  • 1
    @haze also the precidence of postfix/prefix and addition opperators (as well as their symantic meanins) differs by language. For example in c++ the post/prefix have highest precedence, addition the lowest. Likewise in java, however the pfixes have right-to-left associativity, so of those operators, the rightmost ones are performed first. Etc...
  • 2
    At least in C this is undefined/unspecified behavior referring to the C99 standard section 6.5 p. 2 & 3:

    „Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.“

    „...the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.“

    Therefore, it’s up to the compiler how to treat your code yielding different results for different compilers.
  • 0
    @offworld can you please explain it a bit more
  • 0
    @offworld worth noting that undefined behavior <> Unspecified behavior in this case
  • 0
    @ankitbansal The language standard defines the statement as the smallest unit of determinism (the compiler must be able to predict state - apart from actual data, of course - at the beginning and end of each statement). Within each statement each object must be modified at most zero or one times, leaving modifications beyond that undefined (so compilers don't have to try to be "correct" beyond that, as programmers should not try to modify objects more than once - this also enables more aggressive optimizations). Because of this, the compiler will be hampered by its own internals from getting the expected result (assuming it doesn't just give up).
Add Comment