tags:

views:

174

answers:

4

HI ,

Can some one help me in understanding why the value of SQUARE(x) is 49 ?

I am using Visual C++ 6.0 .

#define SQUARE(X) X * X

int main(int argc, char* argv[])
{
    int y = 5;

    printf("%d\n",SQUARE(++y));
    return 0;
}
+11  A: 

Because the macro expands to:

++y * ++y

which gives undefined behaviour in C++ - the result could be anything. This very well known problem should be covered in any decent textbook that covers the use of macros. Which one are you using?

anon
You could also see 6x7=42 depending upon your compiler.
Will Bickford
@Will - or you might not get 42.
Michael Burr
+3  A: 

Because macros do textual substitution so the code you wrote gets expanded to

printf("%d\n",++y * ++y );

and then the order of operations is undefined behaviour so this the compiler sees 2 increments and then a multiplication

So be careful with macros better to use functions which as the compiler can expand inline will not take any longer to run.

Secondly don't assume what will happen if you increment and use variables

Mark
+4  A: 

Macros are not functions: they just alter the text of the program. This operation is called preprocessing and it's automatically executed before your code gets compiled. People write macros to save their time and introduce some variability to their source code.

When you write SQUARE(x), no actual funciton call happens, just the text is modified. The operation is quite dumb, so you have to do additional precautions in cases like yours. Refer to other answers for explanation of your case.

Pavel Shved
+10  A: 

Neil Butterworth, Mark and Pavel are right.

SQUARE(++y) expands to ++y * ++y, which increments twice the value of y.

Another problem you could encounter: SQUARE(a + b) expands to a + b * a + b which is not (a+b)*(a+b) but a + (b * a) + b. You should take care of adding parentheses around elements when needed while defining macros: #define SQUARE(X) ((X) * (X)) is a bit less risky. (Ian Kemp wrote it first in his comment)

You could instead use an inline template function (no less efficient at runtime) like this one:

template <class T>
inline T square(T value)
{
    return value*value;
}

You can check it works:

int i = 2;
std::cout << square(++i) << " should be 9" << std::endl;
std::cout << square(++i) << " should be 16" << std::endl;

(no need to write

square<int>(++i)

because the int type is implicit for i)

moala
Where you have written "no need to write `square(++i)`" I think you mean "no need to write `square<int>(++i)`"; if you *have* written that, you need to use backticks to prevent `<int>` being interpreted as a html tag.
Dave Hinton
@Dave Hinton: thanks, I had not seen it was not rendered.
moala
Always good to provide a decent alternative! +1
xtofl
Just to be clear though - ((++y) * (++y)) increments 'y' twice in terms of what's written in the program text, but it results in undefined behavior which means when the program is run 'y' might be incremented once, twice, thrice, never, or the program might crash. You just don't know what's going to happen.
Michael Burr