14

This question was asked to me in a mock interview...Really got surprised to find awkward answers...

consider a macro:

#define SQR(x) (x*x)

Example 1:

SQR(2) //prints 4

Example 2:

If SQR(1+1) is given it doesn't sum (1+1) to 2 but rather ...

SQR(1+1) //prints 3

Awkward right? What is the reason? How does this code work?

NOTE: I searched SO but couldn't find any relevant questions. If there are any kindly please share it!

Neil Townsend
  • 6,024
  • 5
  • 35
  • 52
abu
  • 249
  • 2
  • 3
  • 11

3 Answers3

47

SQR(1+1) expands to 1+1*1+1 which is 3, not 4, correct?

A correct definition of the macro would be

#define SQR(x) ((x)*(x))

which expands to (1+1)*(1+1) and, more important, shows you one of the reasons you shouldn't use macros where they aren't needed. The following is better:

inline int SQR(int x)
{
    return x*x;
}

Furthermore: SQR(i++) would be undefined behavior if SQR is a macro, and completely correct if SQR is a function.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 3
    Of course, even the "corrected" macro can still surprise you when it evaluates the argument twice. – Mike Seymour Jun 12 '13 at 17:28
  • @MikeSeymour this what you had in mind? – Luchian Grigore Jun 12 '13 at 17:30
  • Hi Luchian. It's simple to see that `x*x` is wrong. Also, `(x*x)` just puts that in parenthses. Can you come up with an example where `(x)*(x)` is more wrong than the final solution `((x)*(x))`? I think we need an operator that has higher precedence than `*`. I can think of `sizeof SQR(x)` go wrong. Is there a more realistic example than that? – Thomas Weller May 17 '23 at 11:59
  • Also, do you know why SQR(i++) is UB? A reference to the C++ standard would be nice. – Thomas Weller May 17 '23 at 12:21
5

The problem is that macros are doing textual substition before it is compiled, so the macro expands to 1+1*1+1 which means 1+(1*1)+1 because of the mathematical rules, which in turn evaluates to 1+1+1 = 3 which is the correct result. That's why you should put that in brackets.

#define SQR(x) ((x)*(x))
Devolus
  • 21,661
  • 13
  • 66
  • 113
5

That is why you always put arguments to macros into ():

#define SQR(x) ((x)*(x))
Philipp T.
  • 793
  • 4
  • 13