Trung Dang
Trung Dang

Reputation: 103

Macro and similar function return different results

I'm quite confusing about this:

    #define prod(x,y) x*y

The following function call prints 11 in the console:

    printf("%d",prod(1+2,3+4));

But when I use prod(x,y) as a function returning x*y, it returns 21. Why the results are different? I thought #define should give prod(x,y) = x*y.

Upvotes: 1

Views: 158

Answers (3)

Edwin Buck
Edwin Buck

Reputation: 70909

With your definition of

#define prod(x,y) x*y

The line

printf("%d",prod(1+2,3+4));

becomes

printf("%d",1+2*3+4);

which will evaluate to

printf("%d",1+6+4);

yielding

11

A function evaluates things differently. With the function

int prod(int x, int y) { return x*y; }

the call

printf("%d",prod(1+2,3+4));

will have to collapse (evaluate) the parameters before they can be passed. This is because C is "pass by value" in it's parameter handling style. Even pointers, which are technically references are turned into values representing the reference and those values are passed. So the call reduces to

printf("%d",prod(3,7));

which inside the function becomes

return 3*7;

or return 21

There's a valueable lesson here. Macros don't understand the language. They are just text substitutions, and they will not honor types, operator precedence, or any other language element you've taken the time to learn. Basically the macro language is a different-than-C language, and a much more primitive one than C.

Upvotes: 1

Klas Lindbäck
Klas Lindbäck

Reputation: 33273

Operator precedence is biting you.

With

#define prod(x,y) x*y

the line

printf("%d",prod(1+2,3+4));

gets expanded to

printf("%d",1+2*3+4);

Note that * has higher precedence than +, so this is evaluated as 1 + (2 * 3) + 4 or 11.

Solution:

Surrround the parameters with parenthesis in your #define:

#define prod(x,y) ((x)*(y))

The line will now be expanded to:

printf("%d",((1+2)*(3+4)));

The purpose of the extra set of parenthesis around the entire expression is to make the expression work as you want when used in conjunction with an operator where evaluation order matters.

prod(4,3)/prod(1,2)) gets expanded to ((4)*(3))/((1)*(2)) or 6. Without the outer parenthesis the expansion would be (4)*(3)/(1)*(2) or 24.

Upvotes: 2

Ruslan Osmanov
Ruslan Osmanov

Reputation: 21492

According to your macro, prod(1+2,3+4) is expanded to 1+2*3+4 which equals to 11. Use parens to fix it:

#define prod(x, y) ((x)*(y))

Upvotes: 1

Related Questions