-1

I found that the precedence and associativity rules are different in C, C++ and Java. Have a look at this code snippet:

#include<stdio.h>
void main(){
    int k = 5;
    int x = ++k*k--*4;
    printf("%d",x);
}

The above C program gives the output as 120

Look the following Java code:

class Main
{
   public static void main(String args[])
   {
      int k = 5;
      int x = ++k*k--*4;
      System.out.println(x);
   }
}

This Java code gives 144 as output. Why this difference? I think the Java evaluation strategy is correct because it is evaluated as (pre increment)6 * 6 (post decrement) *4 = 144

Then what's wrong with C and C++? C and C++ both give 120.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 7
    Undefined behaviour is part of C (and C++). Incrementing and decrementing `k` in a statement like that is UB in C. Nothing is wrong with C or C++. Your expectation that C and Java must behave the same is erroneous, that's all. – Jonathan Leffler May 17 '22 at 02:47
  • 1
    This is not a precedence issue. C and C++ intentionally do not specify the order of evaluation, outside of specific circumstances (such as across short-circuiting `||` and `&&`). – Silvio Mayolo May 17 '22 at 02:48
  • 5
    “Why are two different languages different” because they are. – Taekahn May 17 '22 at 02:48
  • I find that behaviour very surprising. I could have believed 144 or 100. But 120 just seems wrong. – Dawood ibn Kareem May 17 '22 at 02:55
  • 2
    @DawoodibnKareem — 396 would also be valid in C, as would -937. The behaviour is undefined and any result is valid. – Jonathan Leffler May 17 '22 at 02:57
  • 1
    @DawoodibnKareem It’s not expected to conform to what you expect, because the behavior is not defined. This isn’t a math class where every problem has to have a single defined answer. There are like 16 different ways to evaluate that expression. What makes any of those ways more correct than the others? – Taekahn May 17 '22 at 02:59
  • 2
    Personally, I think that C and C++ has the better approach in this particular case (there are other situations where I think Java does it better). Making the behaviour undefined serves to discourage writing of cryptic code that makes code harder to understand, harder for the person writing the code to get right, and harder again for other people to comprehend. More generally, the implicit assumption that C and C++ are wrong and Java is somehow right is simply nonsense - they are different languages, with different purposes, so good techniques in one can be bad techniques in the other. – Peter May 17 '22 at 02:59
  • "I found that the precedence and associativity rules are different in C, C++ and Java": no you didn't. There is no C++ code here, and no apparent difference in the precedence or associativity rules (although those may exist). What you have found is undefined order of evaluation in C, which isn't the same thing as either precedence or associativity. – user207421 May 17 '22 at 04:53
  • I always learnt that prefixed operators like `++k` are evaluated before the current instruction and postfixed operators like `k--` after the current instruction. That said, 144 should be the right answer. By the way, the MSVC compiler gives 144 with this code, not 120. – Joël Hecht May 17 '22 at 05:39
  • The true explanation is that some language defects in C are so old that people have started to think fondly of them, giving their favourite form of UB nicknames and dressing it up in costumes. As well as nostalgia: "Ah yes, using i++ without sequence points, I remember writing that bug back in 1985, oh boy..." There is no sensible reason why these defects must remain in the language (as shown by C++17 fixing part of this language defect). There's not even a sensible reason to mix `i++` with other operands in the same expression. And if you never do, you never have to worry about i++ vs ++i. – Lundin May 17 '22 at 06:36
  • To put it bluntly, Java had the ambition to become a better language, but failing because it insisted on weird stuff like VM and garbage collection - or it would have replaced C and C++ 20 years back. C has the ambition to forever remain a language with plenty of defects. And C++ apparently has the ambition to turn into a worse language by every standard iteration. Making all three languages dysfunctional in various ways. We are still waiting for a sane replacement for ancient C and ancient C++, one suitable for real-time systems. – Lundin May 17 '22 at 06:41

1 Answers1

3

In Java, left to right evaluation of most operands, including side effects, is guaranteed.

C and C++ make no such guarantee. Except for ||, &&, ?: (the ternary operator) and , (the comma operator), the evaluation order of operands is unspecified, as is any side effects that may result.

In this case:

int x = ++k*k--*4; 

The variable k is written to more than once without an intervening sequence point. This triggers undefined behavior.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
dbush
  • 205,898
  • 23
  • 218
  • 273
  • Note that more recent C++ standards (C++11 and later) no longer use the term "sequence point". They simply say that, if side effects on a scalar object are unsequenced relative to other side effects on the same object, then the behaviour is defined. – Peter May 17 '22 at 03:04
  • @Peter They still use the term sequence point, just not in the 6.5/2 part you refer to. It's still a formal term defined in 5.1.2.3. There's weird rumours floating around on SO that sequence points were completely removed. – Lundin May 17 '22 at 14:04