7

Why is the answer for the below code 16? Can anybody explain the working of this program?

#define SQUARE(n) n*n
void main()
{
    int j;      
    j =16/SQUARE(2);

    printf("\n j=%d",j);
    getch();
}

If we write the same code like below, then the answer is 4:

//the ans is 4 why?
#include<stdio.h>
#include<conio.h>

#define SQUARE(n) n*n

void main()
{
    int j;      
    j =16/(SQUARE(2));

    printf("\n j=%d",j);
    getch();
}
4
  • 1
    This is one of many reasons why you should avoid function-like macros. Commented Jan 30, 2013 at 13:40
  • 1
    To parenthesis or not to parenthesis. That is the question. And the answer is use parenthesis whenever you write expressions. Commented Jan 30, 2013 at 13:45
  • Yes, many unexpected things will happen for beginners espicially. Commented Jan 30, 2013 at 13:45
  • 1
    Note that if you had written j = 16 / SQUARE(1 + 1);, your answer would be 18, but if you had written j = 16 / (SQUARE(1 + 1));, your answer would have been 5. Also, the return type of main() should be int. Commented Jan 30, 2013 at 13:54

9 Answers 9

16

The preprocessor just replaces the text, exactly as written.

So, the macro call SQUARE(2) becomes literally 2*2.

In your case, that means the whole expression becomes 16/2*2, which because of C's precedence rules evaluates to (16/2)*2, i.e. 16.

Macros should always be enclosed in parenthesis, and have each argument enclosed as well.

If we do that, we get:

#define SQUARE(n)  ((n) * (n))

which replaces to 16/((2) * (2)), which evaluates as 16/4, i.e. 4.

The parens around each argument makes things like SQUARE(1+1) work as expected, without them a call such as 16/SQUARE(1+1) would become 16/(1+1*1+1) which is 16/3, i.e. not at all what you'd want.

Sign up to request clarification or add additional context in comments.

1 Comment

Superb explaination. Thank you so much unwind.
3

Order of operations. Your expression is evaluating to:

 j = 16 / 2 * 2

which equals 16. Make it:

#define SQUARE(n) (n*n) 

which will force the square to be evaluated first.

1 Comment

Now, i know the answer. Thank you.
3

You need to define your macro with insulating parentheses, like so:

 #define SQUARE(n) ((n)*(n))

Otherwise

 j = 16/SQUARE(2);

expands to

j = 16 / 2 * 2;   which is equivalent to (16 / 2) * 2

When what you want is

j = 16 / (2 * 2);   

Comments

3

1. When using macros that are to be used as expressions, you should parenthesise the whole macro body.

This prevents erroneous expansions like:

#define SQUARE(x) x*x
-SQUARE(5,5)
// becomes -5 * 5

2. If the macro arguments are expreessions, you should parenthesise them too.

This prevents a different type of problems:

#define SQUARE(x) x*x
SQUARE(5+2)
// becomes 5 + 2*5 + 2

Hence the correct way is to write it like this:

#define square(n) ((n)*(n))
-SQUARE(5+2)
// becomes -((5+2)*(5+2))

Using macros as functions is discouraged though (guess why), so use a function instead. For instance:

inline double square(n) { return n*n; }

1 Comment

Thank you Kos. Thanks for you explaination.
2

The Expansion of macro will be like:

  j = 16/SQUARE(2);
  j = 16/2*2;

Which is equal to : j = (16/2)*2; Means j = 16;

and :

 j = 16/(SQUARE(2));
 j = 16/(2*2);

Which is equal to : j = 16/4; Means j = 4;

1 Comment

Thank you Midhun, I got it now.
2

Because the macro will be expanded as:

j = 16/2*2;

The pre-compiler does not do any processing on the expansion. It places the expanded macro in your code as it is. Since you have not parenthesized the replacement text it wont do it for you in the main code as well. Make it :

#define SQUARE(n) ((n)*(n))

2 Comments

Thank you Deepankar, Now I know it.
Although your alternative definition is better, it runs into problems with SQUARE(1+1), which gives 3 with your code. Parenthesize each argument, and the expression as a whole: #define SQUARE(n) ((n) * (n)).
1

The first example is evaluated as:

16 / 2 * 2
(16 / 2) * 2
8 * 2
16

The second example is evaluated as:

16 / (2 * 2)
16 / 4
4

Add parenthesis to you preprocessor statement to control the order of operations:

#define SQUARE(n) ((n)*(n))

The outer parenthesis in ((n)*(n)) ensure that n is squared before any outside operation is performed. The inner parenthesis (n) ensure that n is correctly evaluated in cases where you pass an expression to SQUARE like so:

16 / SQUARE(2 * 2)
16 / ((2 * 2)*(2 * 2))
16 / (4 * 4)
16 / 16
1

1 Comment

Yes Nocturno, now I understand. Thank you so much.
0

you'll get

j =16/2*2; // (16 / 2) * 2 = 16

2 Comments

I think 16/2*2 is same as (16/2)*2 so it is 16. Thank you Johann
*duh* Math is hard... Thanks!
0

It’s because whenever a macro name is used, it is replaced by the contents of the macro. It’s the simple rule of the workings of a macro.

Case 1: result 16

define SQUARE(n) n*n

void main()
{
    int j;
    j = 16/SQUARE(2);

    printf("\n j=%d", j);
    getch();
}

It gets expanded as below:

j = 16/SQUARE(2);

So in place of SQUARE(2), it will replace 2*2, because the macro is SQUARE(n) n*n

j = 16/2*2
j = (16/2)*2
j = 8*2
j =16

Case 2: result 4

define SQUARE(n) n*n

void main()
{
    int j;
    j = 16/(SQUARE(2));

    printf("\n j=%d", j);
    getch();
}

It gets expanded as below:

j = 16/(SQUARE(2));

So in place of SQUARE(2), it will replace 2*2, because the macro is SQUARE(n) n*n

j = 16/(2*2)
j = 16/(4)
j = 4

1 Comment

Re "define SQUARE(n) n*n": That is obviously incorrect. A generous interpretation is that it was caused by problems with formatting here at Stack Overflow.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.