5

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));
}
Community
  • 1
  • 1
Dan Dinu
  • 32,492
  • 24
  • 78
  • 114
  • 16
    `5 + 3 * (5 + 3)` -- What should that be? – Hot Licks Feb 02 '13 at 14:21
  • 2
    Calling a function accepting a variable number of arguments without a prototype in scope is Undefined Behaviour. Your program could as well print "yellow" or transfer money from your bank account to mine. – pmg Feb 02 '13 at 14:46
  • Lots of good answers above and below. In addition, when making use of the preprocessor one needs to have additional debugging skills in their repertoire, which involve running the preprocessor solo (independent from the compiler) and inspecting (and debugging) the source code that it outputs. – Erik Eidt Feb 02 '13 at 16:00
  • Regarding the `void main()` signature: [Read this](http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284376&answer=1044841143) – leemes Feb 02 '13 at 16:17
  • @ErikEidt, or just have a good compiler. Clang, e.g, gives you good diagnostics and is capable to follow macro expansions. – Jens Gustedt Feb 02 '13 at 17:11

5 Answers5

24

Since macros only do textual replacement you end up with:

x + 3 * (x + 3)

which is 29.

You should absolutely always put macro arguments between parentheses.

#define Square(x) ((x)*(x))

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:

#define Square(x) ({    \
    typeof(x) y = (x);  \
    y*y;                \
})
cnicutar
  • 178,505
  • 25
  • 365
  • 392
9

Please note that although the macro

#define Square(x) ((x)*(x))

seems to solve the problem, it does not. Consider this:

int x = 5;
printf("%d\n", Square(x++));

The preprocessor expands this to:

((x++)*(x++))

which is undefined behavior. Some compilers will evaluate this as

(5 * 5)

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):

// C
int SquareI(int x) { return x * x; }
float SquareF(float x) { return x * x; }
double SquareD(double x) { return x * x; }

// C++
template<typename T>
T Square(T x) { return x * x; }

Specifically for GCC, there is another solution, since GCC provides the typeof operator so we can introduce a temporary value within the macro:

#define Square(x) ({ typeof (x) _x = (x); _x * _x; })

Et voila: http://ideone.com/OGu08W

leemes
  • 44,967
  • 21
  • 135
  • 183
  • 2
    This shows a potential problem in (mis)using macros. But macros are not evil, but the programmer, who doesn't understand how it works and still uses it in the wrong way, is the real evil ;) +1 regardless of. – P.P Feb 02 '13 at 15:32
  • @KingsIndian The problem is that most people tend to use macros written like this as functions and don't think about it being a macro. This is what we call *abstraction*, but here it fails. So *yes*, most macros *are* evil. You should at least write them in upper case (as a typical convention) so you know that it's a macro when looking at your code (as long as sticking to this convention). So it's not about misusing them but about misinterpreting written code. Please note that (in serious projects) code is reviewed more often than it is written; `Square(x++)` is likely to be accepted falsely! – leemes Feb 02 '13 at 16:07
  • -1 for the bold "macros are evil" ideology. Macros are evil (as most other tools) if you use them wrong. Not more and less than that. – Jens Gustedt Feb 02 '13 at 16:29
  • @JensGustedt Please see the comment above on that discussion. Macros like this tend to be used as functions and tend to be forgotten to be macros. That's why they are evil. Make your life easier and don't require yourself to remind you of such pitfalls. I didn't mean to say that all macros are evil, but macros which should replace inline-functions. I edited the question. – leemes Feb 02 '13 at 16:30
  • ... not to forget that you *can* (and sometimes *should*) use evil things. Of course, macros have a good right to exist. – leemes Feb 02 '13 at 16:33
  • @leemes, so what? Just because some people write buggy macros? The reasoning does simply not hold. In C (not C++) macros are an important tool, with C11 and its new `_Generic` feature even more. Your post is simply missleading with that respect. – Jens Gustedt Feb 02 '13 at 16:34
  • 1
    Furthermore, overloading in C *is* supported to some extend, and macros and `_Generic` is just the way to go. – Jens Gustedt Feb 02 '13 at 16:35
  • @JensGustedt So what? They still are evil in a way. You have to care about that. If you do, everything is all right... – leemes Feb 02 '13 at 16:36
  • This being said, I never said you shouldn't use macros. I know that they are an important tool. I even put a better macro definition in my answer. I want to stick to the "evil" thing, especially for new programmers macros *are pitfalls*. Don't you agree? – leemes Feb 02 '13 at 16:37
  • Please also note that the question used to be tagged as C++ too, so I wanted to present the template version. In C++, you *clearly* aren't supposed to write a macro for taking the square. Macros don't have such a big right to exist in C++ than they have in C. – leemes Feb 02 '13 at 16:39
  • Or use C++'s `auto` keyword instead? – Cole Tobin Feb 09 '13 at 01:38
  • @ColeJohnson This discussion is about C. In C++, writing an inline template function is much better than a macro. – leemes Feb 09 '13 at 06:28
  • 1
    Macros are more evil in C++ than in C. Since C lacks templates, macros is the right tool to use to achieve function overloading as @JensGustedt said. `_Generic` can be used to write a `Square()` macro that would call one of `SquareI()`, `SquareF()`, or `SquareD()` based on the type of the argument. I do agree it is wrong to prefer a macro when an inline function will work equally as well, but those times you need a macro, you should not try to contort your code to use an inline function instead. – jxh Jul 26 '13 at 02:39
7

Operator precedence. You see, because Square is a macro, not a function, this is what the compiler actually sees:

(x+3*(x+3))

Which operator precedence ends up as:

5 + (3 * (8))

Or 29. To fix the problem:

#define Square(x) ((x)*(x))
Linuxios
  • 34,849
  • 13
  • 91
  • 116
4

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)).

Linuxios
  • 34,849
  • 13
  • 91
  • 116
zeyorama
  • 444
  • 3
  • 12
1

#define square(X) (x*(x)) is a macro, therefore the compiler replaces the macro with the code:

square(x+3) = x+3*(x+3)

     = 5+3*(5+3) = 5+3*(8) = 29
leemes
  • 44,967
  • 21
  • 135
  • 183
NRK
  • 91
  • 7