0

I have the simple following C code

#define Sqrt(A) A * A


int main(void) {

    int A = 10;

    int x = Sqrt(A+1);

    return 0;

}

For some reason, when I used it like that, with A+1, I get x to be 21, which is probably 10+11. My question is, how is the multiplication is being ignored? If I switch the macro with the macro text, I get the right result which is 121.

Thanks.

Assaf Malki
  • 285
  • 2
  • 3
  • 9
  • Always put parenthesis around your macro variables. Remember, they are expanded prior to compilation, so any expansion which could result in odd order of operations can happen. Parenthesis stop that. – xaxxon Jun 09 '13 at 06:35
  • It's this type of behavior that makes some people hate macros. If you can find an alternate method to macros (like defining a function), you should seriously consider that (if you haven't already). – ajp15243 Jun 09 '13 at 06:37

8 Answers8

5

First, your Sqrt is misnamed, should be Square (not square root)

Then, generate the preprocessed form (i.e. with gcc -C -E) and look inside it.

 #define Sqr(A) A * A

 int a = 10;

 int x = Sqr(a+1);

where the last line is expanded as

 int x = a+1 * a+1;

Which is parsed as

 int x = a+(1*a)+1;

Moral of the story, always use extra parenthesis in macro definition, i.e.

 #define Sqr(A) ((A)*(A))

Even with such a definition, Sqr(a++) is probably undefined behavior and at least is naughty.

So you want to avoid macros and actually, learn to use inline functions like

 inline int square(int a) { return a*a; };

BTW, you will want to make it static inline not just inline (and put that in a header file)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
3

'cos

#define Sqrt(A) A * A

makes

Sqrt(A+1);

translate to

A + 1 * A + 1

and A is 10

so you get

10 + 1 * 10 + 1

Now do the maths!

BTW sqrt has seems to say square root not squared!

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
3

You define the macro as A * A. So, Sqrt(A + 1) expands to A + 1 * A + 1, which is, due to operator precedence, equal to 2 * A + 1 - you've got 2 * 10 + 1 = 21.

That's why you should always parenthesize your macros and their arguments:

#define Sqrt(A) ((A) * (A))

By the way, why a macro? What if one day you write Sqrt(A++)? Then you can expect nasal demons. It would be safer to write an inline function instead (horribile dictu, a correctly named inline function):

static inline double square(double x)
{
    return x * x;
}
Community
  • 1
  • 1
2

Inside the macro, A is replaced with whatever was passed into the macro invocation. In this case, that is A+1. This means that the macro gets expanded to:

A+1 * A+1

Due to operator precedence, this is interpreted as A + 1*A + 1, or 10 + 10 + 1 = 21.

Mankarse
  • 39,818
  • 11
  • 97
  • 141
1

You should define the macro as #define Sqrt(A) ((A) * (A))

Naruil
  • 2,300
  • 11
  • 15
0

Macros are substituted literally and then evaluated.

Since multiplication has more priority than addition, when you give A+1 to the macro it becomes 10 + 1 * 10 + 1 => 10 + 10 + 1 => 21

Likewise if you give A+2 ..... 10 + 2 * 10 + 2 => 10 + 20 + 2 => 32.

ajp15243
  • 7,704
  • 1
  • 32
  • 38
Nitin4873
  • 16,804
  • 1
  • 13
  • 15
0

BODMAS rule buddy!! as the previous answers suggests. Multiplication takes place before your addition. Your opertaion Sqrt(A+1) where A = 10 will evaulate to 10+1*10+1 10+10+1 21!!

0
when you call x = MACRO_NAME(A+1); this statement is replace as x = A + 1 * A + 1
in c priority of multiplication is more than addition so it will be 1st executed 1*A which give as A, then A+A+1 will give you result as 21`enter code here`
i.e  A+1*A+1 
  =  A+A+1 
  =  21
for proper answer you need to write Macro as #define MACRO_NAME(A) (A) * (A) which give you result as 
121
reshma
  • 641
  • 1
  • 11
  • 18