Possible Duplicate:
square of a number being defined using #define
Can you please explain why the following code outputs "29"?
#define Square(x) (x*(x))
void main()
{
int x = 5;
printf("%d", Square(x+3));
}
Possible Duplicate:
square of a number being defined using #define
Can you please explain why the following code outputs "29"?
#define Square(x) (x*(x))
void main()
{
int x = 5;
printf("%d", Square(x+3));
}
#define square(X) (x*(x))
is a macro, therefore the compiler replaces the macro with the code:Operator precedence. You see, because Square is a macro, not a function, this is what the compiler actually sees:
Which operator precedence ends up as:
Or 29. To fix the problem:
The preprocessor replaced Square(x) with x*(x).
Your code looks like
printf("%d", x+3*(x))
.You should use
#define Square(x) ((x)*(x))
.Since macros only do textual replacement you end up with:
which is 29.
You should absolutely always put macro arguments between parentheses.
Better yet, use a function and trust the compiler to inline it.
EDIT
As leemes notes, the fact that the macro evaluates
x
twice can be a problem. Using a function or more complicated mechanisms such as gcc statement expressions can solve this. Here's a clumsy attempt:Please note that although the macro
seems to solve the problem, it does not. Consider this:
The preprocessor expands this to:
which is undefined behavior. Some compilers will evaluate this as
which seems as expected in the first place. But
x = 7
afterwards, since the increment operator has been applied twice. Clearly not what you were looking for.For the output, see here: http://ideone.com/9xwyaP
This is why macros* are evil.
(*Macros which tend to be used as a replacement for inline-functions.)
You can fix this in C++ using template functions which can handle all types and in C by specifying a concrete type (since even overloading isn't supported in C, the best you can get is different functions with suffixes):
Specifically for GCC, there is another solution, since GCC provides the
typeof
operator so we can introduce a temporary value within the macro:Et voila: http://ideone.com/OGu08W