2
#include <stdio.h>

main() {
  int i=3,j;  
  j=++i*++i*++i;
  printf("%d,%d",i,j);
}

The answer is upcoming up with i=6, j=150 Please explain why j is coming up with 150??

Sudheesh
  • 65
  • 5
  • 7
    Holy UNDEFINED BEHAVIOR! – haccks Feb 15 '14 at 15:51
  • No return value, j not initialized.. what else can go wrong? – Loïc Faure-Lacroix Feb 15 '14 at 15:53
  • for i=3,j=4*5*6=120.When i=6 this goes j=7*8*9=504. So, I have no idea why j == 150! – ThunderGr Feb 15 '14 at 15:53
  • 2
    You should never write stuff like `j=++i*++i*++i;`. Even if you know about sequence points (and all its consequences), the reader of your code does not know that you know. – Bernd Elkemann Feb 15 '14 at 15:54
  • 1
    @LoïcFaure-Lacroix no problem with `j` not being initialized at declaration, since it is in the following line, also, at last c++ doesn't require a return statement for `main`. – oblitum Feb 15 '14 at 15:55
  • @pepper_chico I'm aware the problem has something to do with the `++` which could be cached or not.. UB. a void main wouldn't require a return. a `int main` should. – Loïc Faure-Lacroix Feb 15 '14 at 15:56
  • its not related to j being uninitialized..its simply UB..http://ideone.com/yeOjq2 – Kamlesh Arya Feb 15 '14 at 15:56
  • @LoïcFaure-Lacroix: no need to initialize, and no need for return value (at least, since C99. http://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c ). so yes, a lot of things can go wrong ;) – Karoly Horvath Feb 15 '14 at 15:57
  • @LoïcFaure-Lacroix in c++ at last, it doesn't require. Not sure about the c standard, I think it's even more relaxed. – oblitum Feb 15 '14 at 15:57
  • 1
    @KarolyHorvath what value will be returned by a `int main` by default then? 0? – Loïc Faure-Lacroix Feb 15 '14 at 15:58
  • 1
    @LoïcFaure-Lacroix: yes. 0. – Karoly Horvath Feb 15 '14 at 15:58
  • What was that editing in order to put the brace on the declaration? It makes the code less readable! – ThunderGr Feb 15 '14 at 15:59
  • The code is perfectly correct!! – Sudheesh Feb 16 '14 at 04:32
  • The code is perfectly correct!! But after complilation the answer is coming i=6, j=150. I don't know why it is giving 150 instead of 120. If i talk about the logic, since we know i++ mean firstly `i=i+1;` then `j=i;` by this, we get i=6 that's perfect right. But at j it should be `j=4*5*6` that will giving 120, but after complilation it is giving 150.! :( – Sudheesh Feb 16 '14 at 04:38

3 Answers3

9

This Undefined behaviour is because of Sequence Points. See these links

Undefined behavior and sequence points

http://c-faq.com/expr/seqpoints.html

Community
  • 1
  • 1
Nishant Kumar
  • 2,199
  • 2
  • 22
  • 43
2

This j=++i*++i*++i in your compiler will break into 1:(++i*++i)*++i then it will calculate the left operand and then the right one. The left one is a parenthesis so it will see what's inside. That ++i*++i will be evaluated as (++i)*(++i), then the compiler will calculate the left and right operands and then it will do the multiplication. The left operand will increase i by one and return i, right operand will increase i by one and will return i. So we got i*i in the first parenthesis of the 1 expression, i is 5 so it will return 25. Now we got (25)*(++i), compiler checks both operands, left one returns 25, right one increases i by one and returns i, i is now 6 so we got 25*6=150. This is how gcc works

Theofilos Mouratidis
  • 1,146
  • 12
  • 32
1

The result is actually depend on the compiler.

I have compiled it with gcc and clang. Gcc outputs 150, and clang outputs 120.

But the disassemble can give the reason why j = 150:

movl   $0x3,-0xc(%rbp)  // i = 3
movl   $0x0,-0x10(%rbp) // j = 0
mov    -0xc(%rbp),%eax  // %eax = i = 3
add    $0x1,%eax        // %eax += 1, %eax = 4 
mov    %eax,-0xc(%rbp)  // move %eax back to i, ie i = 4
mov    -0xc(%rbp),%eax  // %eax = i = 4
add    $0x1,%eax        // %eax = 5
mov    %eax,-0xc(%rbp)  // move %eax back to i, ie i = 5
mov    -0xc(%rbp),%eax  // store i in %eax
mov    -0xc(%rbp),%ecx  // store i in %ecx
imul   %ecx,%eax        // %eax * %ecx, %eax = 5*5 = 25
mov    -0xc(%rbp),%ecx  // store i in %ecx
add    $0x1,%ecx        // %ecx + 1, %ecx = 6
mov    %ecx,-0xc(%rbp)  // move %ecx back to i, ie i = 6 
mov    -0xc(%rbp),%ecx  // store i in %ecx
imul   %ecx,%eax        // %eax * %ecx, %eax = 6*25=150
mov    %eax,-0x10(%rbp) // move %eax to j, ie j = 150
Kang Li
  • 606
  • 7
  • 10