Problem with Macros
Asked Answered
C

4

6

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;
}
Caracole answered 29/8, 2009 at 10:15 Comment(3)
Ah, this old chestnut... to get the correct result you should use: #define SQUARE(X) ((X) * (X)).Winthrop
@Ian Wrong, I'm afraid.Lakes
The comment of Ian Kemp is indeed wrong on the fact that it does not resolve the problem. However, it's right that it's better, in macros, to add parentheses: SQUARE(a + b) expands into a + b * a + b which is not (a+b)*(a+b) but a + (b*a) + b.Moorer
M
17

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)

Moorer answered 29/8, 2009 at 10:57 Comment(2)
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.Harar
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.Purapurblind
L
15

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?

Lakes answered 29/8, 2009 at 10:18 Comment(2)
You could also see 6x7=42 depending upon your compiler.Scrobiculate
@Will - or you might not get 42.Purapurblind
K
5

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

Klaxon answered 29/8, 2009 at 10:21 Comment(0)
L
5

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.

Limestone answered 29/8, 2009 at 10:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.