This question already has answers here:
Preprocessor macro in C
(3 answers)
Closed 5 years ago.
I am learning C in depth. But I am not getting this program. Somebody, please tell me how the output of the below program is m=2, n=3
#include <stdio.h>
#define MAX(a,b) a>b ? a:b
int main()
{
int m,n;
m=3+MAX(2,3);
n=2*MAX(3,2);
printf("m=%d, n=%d\n",m,n);
return 0;
}
This is why parenthesis in macro definitions are important.
A macro does simple text substitution. So when you do this:
m=3+MAX(2,3);
It expands to this:
m=3+2>3 ? 2:3
With the implicit parenthesis:
m = ((3+2)>3) ? 2:3
Which is probably not what you want.
You need to put parenthesis around the entire macro as well as around each argument wherever it is used:
#define MAX(a,b) ((a)>(b) ? (a) : (b))
This will then expand to:
m = 3 + ((2)>(3) ? (2):(3))
Also note that with a macro like this you open yourself up to side effects of one of the operands. For example, if you did this:
int a=2, b=3;
m = MAX(a++,b);
You would get:
int a=2, b=3;
m = ((a++) > (b) ? (a++) : (b));
This invokes undefined behavior because it attempts to modify a more than once in an expression without a sequence point.
This is what happens in your case:
int main() {
int m,n;
m=3+2>3 ? 2:3; //(3+2)>3 ? 2 : 3 = 2
n=2*3>2 ? 3:2; //(2*3)>2 ? 3 : 2 = 3
printf("m=%d, n=%d\n",m,n);
return 0;
}
If you rewrite your defined to #define MAX(a,b) ((a)>(b) ? (a):(b))
then you will have desired output as it will be evaluated to:
//Correct way with parenthesis
int main() {
int m,n;
m=3+((2)>(3) ? (2):(3)); //6
n=2*((3)>(2) ? (3):(2)); //6
printf("m=%d, n=%d\n",m,n);
return 0;
}
Related
I've just started learning C and I need some help with understanding macrocommands. I wanted to create one which calculates the maximum between two numbers.
I know the names are not chosen quite well, but it is just for testing purposes.
Here's the code:
#include <stdio.h>
#define max(a, b) (int max2, a>=b ? max2 = a : max2 = b)
void main()
{
int a, b;
scanf("%d%d", &a, &b);
int maximum = max(a, b);
printf("%d", maximum);
}
I'm getting an error on line 8, (the one with int maximum = max(a, b) ) saying "expected a ')'".
I guess that's because I'm using the preprocessor wrong (in my opinion), but I don't know how I should do it properly in this case.
Can anybody help me understand what am I doing wrong and how I should use preprocessors? Thanks.
I don't think you understand how a macro works; you don't declare a new variable max2 inside it. The preprocessor is a simple text substitution system.
Your macro expands to:
int maximum = (int max2, a>=b ? max2 = a : max2 = b);
This is a syntax error. A max macro is very simple, all you need is:
#define max(a, b) ((a) >= (b)) ? (a) : (b)
This will then expand to:
int maximum = ((a) >= (b)) ? (a) : (b);
Which will give you the result you want.
What you have written, comes down to:
int maximum = (int max2, a>=b ? max2 = a : max2 = b); // this looks weird (what's that max2 for?)
Why don't you simply write the following:
#define max(a, b) ((a)>=(b) ? (a) : (b))
Like this, your line of code becomes:
int maximum = ((a)>=(b) ? (a) : (b));
Which looks a lot more logical. (Briefly, you don't need max2)
#include <stdio.h>
#define abs(x) (x < 0 ? -x : x)
int x;
int doubleGlobalX()
{
x*=2;
return x;
}
int main()
{
scanf("%d",&x);//5
printf("%d\n",abs(doubleGlobalX()));//20
return 0;
}
When the input is 5 the output of this code is 20. When input is 15 the output is 60. Don't know why it doubles the global twice.
#define abs(x) (x < 0 ? -x : x)
Macros perform textual substitution. Defining an abs() macro like this is a well-known trap because it ends up evaluating x twice. If it were a function it'd be fine, but as a macro it's a problem. abs(doubleGlobalX()) expands to:
doubleGlobalX() < 0 ? -doubleGlobalX() : doubleGlobalX()
It ends up calling doubleGlobalX() twice which causes x to be doubled twice.
I was just going through certain code which are frequently asked in interviews. I came up with certain questions, if anyone can help me regarding this?
I am totally confused on this now,
#include <stdio.h>
#include <conio.h>
#define square(x) x*x
main()
{
int i, j;
i = 4/square(4);
j = 64/square(4);
printf("\n %d", i);
printf("\n %d", j);
printf("\n %d", square(4));
getch();
}
The output is:
4
64
16
I am wondering, why did square(4) return 1 when I divided it? I mean, how can I get the value 4 and 64 when I divide it, but when used directly I get 16!!?
square is under-parenthesized: it expands textually, so
#define square(x) x*x
...
i=4/square(4);
means
i=4/4*4;
which groups as (4/4) * 4. To fix, add parentheses:
#define square(x) ((x)*(x))
Still a very iffy #define as it evaluates x twice, so square(somefun()) calls the function twice and does not therefore necessarily compute a square but rather the product of the two successive calls, of course;-).
When you write i=4/square(4), the preprocessor expands that to i = 4 / 4 * 4.
Because C groups operations from left to right, the compiler interprets that as i = (4 / 4) * 4, which is equivalent to 1 * 4.
You need to add parentheses, like this:
#define square(x) ((x)*(x))
This way, i=4/square(4) turns into i = 4 / ((4) * (4)).
You need the additional parentheses around x in case you write square(1 + 1), which would otherwise turn into 1 + 1 * 1 + 1, which is evaluated as 1 + (1 * 1) + 1, or 3.
i=4/square(4);
expands to
i=4/4*4;
which equivalent to
i=(4/4)*4;
Operator precedence is hurting you.
The macro is expanded by the pre-processor such that
i=4/4*4;
j=64/4*4;
which is equivalent to:
i=(4/4)*4;
j=(64/4)*4;
That's because the compiler replaces it with:
i=4/4*4;
j=64/4*4;
i = (4/4)*4 = 1*4 = 4.
j = (64/4)*4 = 16*4 = 64.
j = 4/square(4) == 4/4*4 == 1*4 == 4
Manually expand the macro in the code, and it will be clear. That is, replace all the square(x) with exactly x*x, in particular don't add any parentheses.
define is just a text macro
main()
{
int i,j;
i=4/ 4 * 4; // 1 * 4
j=64/4 * 4; // 16 * 4
printf("\n %d",i);
printf("\n %d",j);
printf("\n %d",square(4));
getch();
}
It's a macro! So it returns exactly what it substitutes.
i = 4/4*4; Which is 4...
j = 64/4*4; Which is 16...
Try this for your macro:
#define square(x) ((x)*(x))
Because of operator precedence in the expression after the preprocessor - you'll need to write
#define square(x) (x*x)
As the other answers say, you're getting burned by operator precedence. Change your square macro to this:
#define square(x) (x*x)
and it'll work the way you expect.
Why the output is "0 -6" and not "4 60"? Isn't k=8, l=2?
#define MAC(a,b) (a<b ? a*b:a-b)
void main (void)
{
int i=2;
int j=4;
int k=MAC(i,j);
int l=MAC(j,i);
i=MAC(k+l,k-l);
j=MAC(k-l,k+l);
printf("%d %d\n", i,j);
}
One immediate problem. The expression
MAC(k+l,k-l)
becomes
(k+l<k-l ? k+l*k-l:k+l-k-l)
^^^^^^^
and, as you can see from the underlined bit, the expression is not what you think it is due to the precedence rules (multiplication is done before addition).
This can be fixed by ensuring each argument in the macro is parenthesised:
#define MAC(a,b) ((a)<(b) ? (a)*(b):(a)-(b))
but that still won't help if you pass in something like n++ as it will be incremented multiple times.
Macros are very simple text substitutions and are well known to cause problems such as what you're seeing. My advice would be to turn MAC into a proper function that will avoid the problem completely, something like:
int mac (int a, int b) {
if (a < b)
return a * b;
return a - b;
}
#define MAC(a,b) (a<b ? a*b:a-b)
void main (void)
{
int i=2;
int j=4;
int k= i<j ? i*j:i-j;
int l= j<i ? j*i:j-i;
i= k+l<k-l ? k+l*k-l:k+l-k-l;
j= k-l<k+l ? k-l*k+l:k-l-k+l;
printf("%d %d\n", i,j);
}
This is what was produced after your code got preprocessed. preprocess macro happens before compilation. unlike compilation, there is no symbolic linking of variables that have occurred, but a mere 1 to 1 replacement of what you have defined.
This question already has answers here:
C macros and use of arguments in parentheses
(2 answers)
Closed 4 years ago.
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;
}
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.
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))
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.
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.