2

Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
What problems might the following macro bring to the application?

I wrote a sample application with macro expansion for implementing it in my iOS (Objective C code).

It is something like:

#define SQUARE(x) ( x * x )
main( )
{
   int i = 3, j, k ;
   j = SQUARE( i++ ) ;
   k = SQUARE( ++i ) ;
   printf ( "\nValue of i++ = %d\nValue of ++i = %d", j, k ) ;
}

The output was:

Value of i++ = 9
Value of ++i = 49

Expected output was:

 Value of i++ = 9
 Value of ++i = 25

I'm surprised by this result. I'm little bit confused with this macro expansion.

Why did it happen? Please help me to find the reason.

Community
  • 1
  • 1
Midhun MP
  • 103,496
  • 31
  • 153
  • 200
  • I suppose you could fix the code by writing `#define SQUARE(x) ( (0,x) * (0,x) )`, which introduces a sequence point. You should _always_ parenthesis every macro parameter to avoid bugs. But the sober, sensible solution is to not use icky, function-like macros and always keep the ++ operator on a line of its own. – Lundin Jan 21 '13 at 10:11

3 Answers3

6

You are invoking undefined behaviour by modifying the i more than once without an intervening sequence point.

After the marco subsitution, the two lines will look like this:

   j = ( i++ * i++ ) ;
   k = ( ++i * ++i ) ;
P.P
  • 117,907
  • 20
  • 175
  • 238
6

This is really undefined behavior (and should not be relied on on another compiler or even the next run of the same compiler) since it increases the same variable twice in the same statement without a sequence point, but this is what seems to happen in this case;

#define SQUARE(x) ( x * x )
j = SQUARE( i++ ) ;
k = SQUARE( ++i ) ;

will expand to

j = (i++ * i++);     // Compiler could do i * i, then increment twice, or use i * (i + 1), or...  

k = (++i * ++i);     // Same as above

As this is undefined behaviour, the compiler is free to do whatever it wants (old versions of gcc made the program launch nethack ;-). To be more precise: The compiler is free to assume undefined behaviour won't ever be called upon, and just make sure the code works correctly in "normal" cases. What happens in unexpected cases is anybody's bet.

vonbrand
  • 11,412
  • 8
  • 32
  • 52
Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • 1
    There can't be any explanation for UB. Once UB is invoked, nobody knows compiler is going to behave/evaluate. – P.P Jan 21 '13 at 09:48
  • 1
    @KingsIndian: in general, yes. But we can reason about the cause of a particular outcome of UB. – Oliver Charlesworth Jan 21 '13 at 09:58
  • @KingsIndian Agreed that UB in general cannot be explained, however since the compiler has to choose a particular outcome, a specific instance of UB can be explained. In this case I found it useful to the asker to both mention that it's UB and how the compiler seemingly interprets the code in this particular case. – Joachim Isaksson Jan 21 '13 at 10:01
  • This may well happen with one compiler. But on a different compiler, this doesn't have to happen. In fact, the same compiler may exhibit different behaviour on another run (very unlikely though). So any explanation is only going to be misleading. – P.P Jan 21 '13 at 10:02
1

This is because you are incrementing single variable twice between two sequence points. Hence this is a undefined behaviour

   int i = 3, j, k ;
   j = SQUARE( i++ ) ; // it becomes (i++ * i++)
   k = SQUARE( ++i ) ; // it becomes (++i * ++i)

hence the output coming is undefined.

the output that you are getting is because after first xpression i is to be incremented twice so in secon expression where i is getting incremented twice due to pre increment it also gets incremented twice for above post increment.

j=(i++ * i++)//it comes 3*3 

k=(++i * ++i)// it comes 7 as two increments of above xpression
Tushar Mishra
  • 177
  • 1
  • 7