2

Possible Duplicate:
Undefined Behavior and Sequence Points

I am having trouble in understanding the following macro:

#define CUBE(x) ((x)*(x)*(x))

My code:

int y=5;
print("Cube = %d",CUBE(++y));

This piece of code prints 512 (Using Microsoft Visual Studio)

I was expecting this to print: ((++5)*(++6)*(++7)) = (6*7*8) = 336.
How this is evaluated?

Also the same code was compiled using Dev C++ compiler and the result is 392!!!

Can someone explain why two compilers show different results for exactly same code?

How is this ++y evaluated?

Community
  • 1
  • 1
Mahesha Padyana
  • 431
  • 6
  • 22

5 Answers5

3

When the macro is expanded the value of y gets modified more than once without an intervening sequence point.
This is Undefined Behavior.

Undefined Behavior means that any behavior is possible, Your program is not a valid c program.
Hence you see different outputs on different compilers.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

CUBE(++y)); becomes (++y * ++y * ++y) - what order is that evaluated in ?

To be technical - it's undefined to change the same variable between function points

edit: see Undefined behavior and sequence points

Visual C++ seems to evaluate this as y+=3; y*y*y; so 8*8*8 = 512
382 is 7*7*8 so Dev C++ presumably evaluates the first part as y+=2; y*y; then 49*y++

Community
  • 1
  • 1
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
1

There are no sequence points in your expression, so the time when the side effects (i.e. the results of incrementing y) become visible is undefined. In plain words, the compiler is free to store the result of ++y back into the y at any time before the evaluation of the expression is completed.

This is the danger of making macros that take expressions with side effects. You would be much better off with an equivalent function.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

Pre-compiler evaluates this macro

#define CUBE(x) ((x)*(x)*(x))

in your code:

int y=5;
print("Cube = %d",CUBE(++y));

to

int y=5;
print("Cube = %d",((++y)*(++y)*(++y)));

Writing such code is confusing and result is undefined.

Different compilers can behave differently.

Avoid using such construction and you will not facing such issues.

rkosegi
  • 14,165
  • 5
  • 50
  • 83
0

We need to see the ASM (assemble) of the code (gcc -S .c) to know what exactly it is happening.

In Dev C++ Compiler ASM looks like

1)        movl    $5, 28(%esp)
2)        addl    $1, 28(%esp)
3)        addl    $1, 28(%esp)
4)        movl    28(%esp), %eax
5)        imull   28(%esp), %eax
6)        addl    $1, 28(%esp)
7)        imull   28(%esp), %eax

It shows the value 5 was moved to %esp (1) and then added two time there (2 & 3), so now the value of y becomes 7; This value is now moved to eax register (4) and got multiplied 7 * 7 (5); Now add 1 to value y (6) and then multiply with eax; so the answer is 7 * 7 * 8 = 392

In Microsoft visual studio it will be of 8 * 8 * 8.

Viswesn
  • 4,674
  • 2
  • 28
  • 45