Arvind Lairenjam
Arvind Lairenjam

Reputation: 981

How does the preprocessor work in C?

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();
}

Upvotes: 7

Views: 1862

Answers (9)

Ganesh
Ganesh

Reputation: 924

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

Upvotes: 0

Johann Gerell
Johann Gerell

Reputation: 25591

you'll get

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

Upvotes: 0

Deepankar Bajpeyi
Deepankar Bajpeyi

Reputation: 5869

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

Upvotes: 2

Midhun MP
Midhun MP

Reputation: 107191

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;

Upvotes: 2

Nocturno
Nocturno

Reputation: 9997

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

Upvotes: 1

unwind
unwind

Reputation: 399949

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.

Upvotes: 16

Kos
Kos

Reputation: 72279

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; }

Upvotes: 3

Mitch Wheat
Mitch Wheat

Reputation: 300719

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

Upvotes: 3

CJ_912
CJ_912

Reputation: 67

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.

Upvotes: 3

Related Questions