Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
104 views
in Technique[技术] by (71.8m points)

c++ - #define SQR(x) x*x. Unexpected Answer

Why this macro gives output 144, instead of 121?

#include<iostream>
#define SQR(x) x*x

int main()
{
    int p=10;
    std::cout<<SQR(++p);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is a pitfall of preprocessor macros. The problem is that the expression ++p is used twice, because the preprocessor simply replaces the macro "call" with the body pretty much verbatim.

So what the compiler sees after the macro expansion is

std::cout<<++p*++p;

Depending on the macro, you can also get problems with operator precedence if you are not careful with placing parentheses where needed.

Take for example a macro such as

// Macro to shift `a` by `b` bits
#define SHIFT(a, b)  a << b

...

std::cout << SHIFT(1, 4);

This would result in the code

std::cout << 1 << 4;

which may not be what was wanted or expected.


If you want to avoid this, then use inline functions instead:

inline int sqr(const int x)
{
    return x * x;
}

This has two things going for it: The first is that the expression ++p will only be evaluated once. The other thing is that now you can't pass anything other than int values to the function. With the preprocessor macro you could "call" it like SQR("A") and the preprocessor would not care while you instead get (sometimes) cryptical errors from the compiler.

Also, being marked inline, the compiler may skip the actual function call completely and put the (correct) x*x directly in the place of the call, thereby making it as "optimized" as the macro expansion.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...