2

I am new to c language. I just wanted to know why is my macro not working properly. It is giving me output as 13 where as my expected output is 24.?

#include<stdio.h>
#define mult(a,b) a*b
int main()
{
    int x=4,y=5;
    printf("%d",mult(x+2,y-1));
    return 0;
}
user2565192
  • 694
  • 1
  • 8
  • 19
  • 5
    Pipe it through the preprocessor, apply elementary maths, then regret not having obeyed to the rule "always parenthesize macro arguments". Oh, and next time think twice before using a macro. And then don't use a macro but write a (possibly `inline`) function instead. –  Jul 09 '13 at 16:05
  • 1
    It needs to be `#define mult(a,b) ((a)*(b))`. That is causing the problem. – Aseem Bansal Jul 09 '13 at 16:09

4 Answers4

6

mult(x+2,y-1) expands to x +2 * y -1 that is equals to 4 + 2 * 5 -1 gives output: 13.

You might be expecting answer (4 + 2) * (5 -1) = 6 * 4 = 24. To make it expand like this you should write parenthesize macro as @H2Co3 also suggesting:

#define mult(a,b) ((a)*(b))

Read aslo: So, what's wrong with using macros? by Bjarne Stroustrup.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
5

This is because C macros are simple textual substitutions, the macro writer must be sure to insert parentheses around every macro variable when it is substituted, and around the macro expansion itself, to prevent the resulting expansion from taking on new meanings.

If you observe your program: mult(a, b) is defined as a * b

mult(x + 2, y - 1) = x + 2 * y - 1 = 4 + 2 * 5 - 1 = 4 + 10 - 1 = 13

The Correct way would be:

mult(a, b) ((a) * (b))
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
poorvank
  • 7,524
  • 19
  • 60
  • 102
2

Because it replaces the arguments literally:

mult(x+2,y-1) --> mult(4+2,5-1) --> 4 + 2*5 - 1 --> 13

Try changing the define to:

#define mult(a,b) (a)*(b)

In this case the result after pre-processing is this:

int main()
{
    int x=4,y=5;
    printf("%d",(x+2)*(y-1));
    return 0;
}

This will solve the problem but it's still not the best way to do it.

#define mult(a,b) ((a)*(b))

This version is considered as good practice because in other types of situation the first one would fail. See the bellow example:

#include<stdio.h>
#define add(a,b) (a)+(b)
int main()
{
    int x=4,y=5;
    printf("%d",add(x+2,y-1)*add(x+2,y-1));
    return 0;
}

In this case it would give an incorrect answer because it is translated by the pre-processor to the fallowing:

int main()
{
    int x=4,y=5;
    printf("%d",(x+2)+(y-1)*(x+2)+(y-1));
    return 0;
}

printing 34 instead of 100.
For the ((a)+(b)) version it would translate to:

int main()
{
    int x=4,y=5;
    printf("%d",((x+2)+(y-1))*((x+2)+(y-1)));
    return 0;
}

giving a correct answer.

ionela.voinescu
  • 384
  • 1
  • 7
  • Nah. Try changing it to `((a)*(b))` in order to get used to the habit of always parenthesizing everything. –  Jul 09 '13 at 16:12
  • No. That's not a good reason. Habits unjustified and not explained properly don't hold. – ionela.voinescu Jul 09 '13 at 16:54
  • @iionela.voinescu -- euh, unjustified? Why? Isn't this very question enough justification? Also, [read this](https://www.kernel.org/doc/Documentation/CodingStyle), there are plenty of good reasons in there to parenthesize stuff. –  Jul 09 '13 at 16:57
  • 1
    The user how posted the question said he is new to programming in C. I don't need your comment to be explained to me, but he might. Instead of just saying that's a good habit you should have explained why that is, properly, in a separate answer. Things like these always remain better in someone's mind if they are properly explained. – ionela.voinescu Jul 09 '13 at 17:03
2

Use parentheses in the macro definition

#include<stdio.h>
#define mult(a,b) ((a)*(b))
int main()
{
    int x=4,y=5;
    printf("%d",mult(x+2,y-1));
    return 0;
}

This is because different arithmetic operators have different precedence levels. Hence always use parentheses while defining the macro.

Nithin Bhaskar
  • 686
  • 1
  • 5
  • 9