Macros with arguments
Like a function, even a macro can be defined with arguments. It has the name, arguments and replacement text.
Here rather sending arguments and returning value, it works purely on textually substitution. The replacement text is just substituted by preprocessor wherever Macro accurse.
Now we see the fact through an example
#include<stdio.h> #define MAX(x,y) x>y?x:y #define MIN(x,y) x<y?x:y int main() { int a,b,big,small; printf("Enter two numbers:\n"); scanf("%d%d",&a,&b); if(a==b) printf("Equal"); else { big=MAX(a,b); small=MIN(a,b); printf("Biggest number %d",big); printf("\nSmallest number %d",small); } return 0; }
Execution:
Enter two numbers:
45
45
Equal
Execution:
Enter two numbers:
45
12
Biggest number 45
Smallest number 12
prog.c 4: int main() prog.c 5: { prog.c 6: int a,b,big,small; prog.c 7: printf("Enter two numbers:\n"); prog.c 8: scanf("%d%d",&a,&b); prog.c 9: if(a==b) prog.c 10: printf("Equal"); prog.c 11: else prog.c 12: { prog.c 13: big=a>b?a:b; prog.c 14: small=a<b?a:b; prog.c 15: printf("Biggest number %d",big); prog.c 16: printf("\nSmallest number %d",small); prog.c 17: } prog.c 18: return 0; prog.c 19: }
By looking at the expanded source we could observe that, MAX(a,b) is replaced with its replacement text a>b?a:b and MIN(a,b) is replaced with its replacement text a<b?a:b
Care must be taken while writing macros with arguments. It is always better to see the expanded source to see how the macros are getting replaced in the source
Now we will see some of the cases where logic may go wrong due to improper testing of macro definitions
Example:
#define SQUARE(x) x*x
Wile using this macro, the replacement text to SQUARE(10) is 10*10. There may be no problem with this.
The replacement text to SQUARE(3+1) is 3+1*3+1, which results 7 instead 16. It is because * has more priority than +, hence 1*3 evaluates first and then 3, 1 are added to the result
It can be rectified by modifying the macro definition as
#define SQUARE(x) (x)*(x)
So that, the replacement text to SQUARE(3+1) would be (3+1)*(3+1), which results 16
What would be the output of following program?
#include<stdio.h> #define S(x) x*x int main() { int a,b,c,d,e; int n=10; a=S(5); b=S(2+2); c=S(3+1); d=S(1+3); e=S(++n); printf("a=%d",a); printf("\nb=%d",b); printf("\nc=%d",c); printf("\nd=%d",d); printf("\ne=%d\n",e); return 0; }Show Output
Output:
a=25
b=8
c=7
d=7
e=144
Now we will realize this by looking at its expanded code
prog.c 3: int main() prog.c 4: { prog.c 5: int a,b,c,d,e; prog.c 6: int n=10; prog.c 7: a=5*5; prog.c 8: b=2+2*2+2; prog.c 9: c=3+1*3+1; prog.c 10: d=1+3*1+3; prog.c 11: e=++n*++n; prog.c 12: printf("a=%d",a); prog.c 13: printf("\nb=%d",b); prog.c 14: printf("\nc=%d",c); prog.c 15: printf("\nd=%d",d); prog.c 16: printf("\ne=%d\n",e); prog.c 17: return 0; prog.c 18: }
Specification: Accept the radios and print the area, circumference using macros AREA, CIR
#include<stdio.h> #define PI 3.14 #define AREA(x) (PI*x*x) #define CIR(x) (2*PI*x) int main() { int rad; float a,c; printf("Enter the radios:"); scanf("%d",&rad); a=AREA(rad); c=CIR(rad); printf("Area of circle %f",a); printf("\nCircumference of circle %f",c); return 0; }
Execution:
Enter the radios: 5
Area of circle 78.500000
Circumference of circle: 31.400000
Specification: Accept any character and print whether the character is a vowel, consonant, digit or special symbol
#include<stdio.h> #define AND && #define OR || #define ISVOWEL(x) (x=='a' OR x=='e' OR x=='i' OR x=='o' OR x=='u') #define ISCONS(x) (x>='b' AND x<='z') #define ISDIG(x) (x>='0' AND x<='9') int main() { char alp; printf("Enter any alphabet:"); scanf("%c",&alp); if(ISVOWEL(alp)) printf("Vowel"); else if(ISCONS(alp)) printf("Consonant"); else if(ISDIG(alp)) printf("Digit"); else printf("Spacial symbol"); return 0; }
Execution:
Enter any alphabet: 7
Digit
Macro vs. function:
In the above examples, macros were used to calculate area, circumference of circle and to find category of a character. Though macro calls are similar to function calls, they are not really same things.
In case of macros, replacement text is just replaced with macro along the source. It increases the size of source code but increases the performance of program because in case of functions, it takes time to call a function and getting control back
Complex logic can’t be replaced with macros rather functions need to be used
In case of functions, size of source code would not be changed as we call the function for any number of times but, takes some time every time a function is called. Complex logic can be implemented using functions, but not possible with macros
Conclusion is that, use macro where speed is critical and used functions, where space is critical
Macro parameters are generic:
Unlike functions, formal arguments of a macro are generic, accepts any type of actual arguments. Say for example, if we want to define a function that takes two integers and returns sum of them then the function would be
int sum(int x,int y) { return x+y; }
If we want to define a function that accepts two floating point values and returns sum of them then the function would be
float sum(float x,float y) { return x+y; }
In case of macro with parameters, it is enough to define a single macro to handle both integer and floating point types.
#include<stdio.h> #define SUM(x,y) (x)+(y) int main() { int s1=SUM(10,20); float s2=SUM(12.34f,56.34f); printf("Sum of integers %d",s1); printf("\nSum of floating point types %f",s2); return 0; }
Output:
Sum of integers 30
Sum of floating point types 68.680000