12.4 – Preprocessor Directives – Macro substitution

by subbu on December 17, 2013

C provides a language feature called preprocessor. It is a special step in compiler chain. C statements start with # symbol are processed by the preprocessor before compilation. The result of preprocessor is expanded source, which will be input to the compiler.

In previous session, we have discoursed how Expanded source can be generated in different platforms

Types of preprocessor directives:

C language supports different preprocessor statements like

  • Macro substitution
  • File inclusions
  • Conditional inclusion/Compilation
  •  operators

Rules in writing preprocessor directives

We must follow certain rules while writing preprocessor statement, Some of these rules are

  • All preprocessor directives must be started with # symbol
  • Every preprocessor statement may be started from the first column (Optional)
  • There shouldn’t be any space between # and directive
  • A preprocessor statement must not be terminated with a semicolon
  • Multiple preprocessor statements must not be written in a single line
  • Preprocessor statements can be written any where within the block, function or outside any function

Macro substitution

Macro substitution has a name and replacement text, defined with #define directive. The preprocessor simply replaces the name of macro with replacement text from the place where the macro is defined in the source code.

Macro substitution

Now we will see the fact through an example.

/* Prog.c */
#include<stdio.h>
#define NUM int
#define OUT printf
NUM main()
{
 NUM a,b,c;
 a=45;
 b=25;
 c=a+b;
 OUT("Sum %d",c);
 return 0;
}

In the above example NUM, OUT are two macros and having their replacement text. The preprocessor replaces the macro names with their replacement text as


/* Prog.i */
 prog.c 3: int main()
 prog.c 4: {
 prog.c 5: int a,b,c;
 prog.c 6: a=45;
 prog.c 7: b=25;
 prog.c 8: c=a+b;
 prog.c 9: printf("Sum %d",c);
 prog.c 10: return 0;
 prog.c 11: }

The above code is intermediate or expanded source generated by C preprocessor. Here we can find the replacement of macros with their replacement text.

  1. While defining a macro, name of macro is written in capitals to identify that it is a macro and the replacement text may be a constant, a word, a statement or a part of program. While defining a macro in multiple lines \ is placed at the end of each line
  2. Macro is not a variable, takes no space; its value can’t be changes by assigning a new value
  3. The scope of macro is from its point of declaration to the end of source file being compiled
  4. A macro definition may use previous macro definition
  5. Macro substitution is only done for tokens but not for strings
  6. A macro can be undefined using #undef

Point 1:

Constant as macro

Example:


#define PI 3.14
#include<stdio.h>
int main()
{
 int rad;
 float area,cir;
 printf("Enter the radios:");
 scanf("%d",&rad);
 printf("Area %f",PI*rad*rad);
 printf("\nCircumference %f",2*PI*rad);
 return 0;
}

Execution:
Enter the radios: 15
Area 706.500000
Circumference 94.200005

Example explained:

Show Expanded Source

 Prog.c 3: int main()
 prog.c 4: {
 prog.c 5: int rad;
 prog.c 6: float area,cir;
 prog.c 7: printf("Enter the radios:");
 prog.c 8: scanf("%d",&rad);
 prog.c 9: printf("Area %f",3.14*rad*rad);
 prog.c 10: printf("\nCircumference %f",2*3.14*rad);
 prog.c 11: return 0;
 prog.c 12: }

While executing the program PI is replaced with 3.14 by preprocessor in the source code.

If we want to change the value of PI as 3.142857 in place of 3.14 then we no need to change the total program rather it is enough to change the macro definition as

#define PI 3.142857

Specification: Accept the current month energy meter reading and previous month meter reading and print the power bill.


#define C 6.80
#define I 12.50
#define A 0.50
#include<stdio.h>
int main()
{
 int cmr,pmr,nu;
 char type;
 float bill;
 printf("The type of connection [domestic/commercial/industrial/agriculture] d/c/i/a:");
 scanf("%c",&type);
 printf("Enter the current month meter reading:");
 scanf("%d",&cmr);
 printf("Enter the previous month meter reading:");
 scanf("%d",&pmr);
 nu=cmr-pmr;
 if(type=='d')
 bill=nu*D;
 else if(type=='c')
 bill=nu*C;
 else if(type=='i')
 bill=nu*I;
 else
 bill=nu*A;
 printf("Number of units consumed %d",nu);
 printf("\nTotal bill %f",bill);
 return 0;
}

Execution:
The type of connection [domestic/commercial/industrial/agriculture] d/c/i/a: c
Enter the current month meter reading: 500
Enter the previous month meter reading: 200
Number of units consumed: 300
Total bill 2040

Example explained:

Show Expanded Source

 prog.c 6: int main()
 prog.c 7: {
 prog.c 8: int cmr,pmr,nu;
 prog.c 9: char type;
 prog.c 10: float bill;
 prog.c 12: printf("The type of connection [domestic/commercial/industrial/agriculture] d/c/i/a:");
 prog.c 13: scanf("%c",&type);
 prog.c 14: printf("Enter the current month meter reading:");
 prog.c 15: scanf("%d",&cmr);
 prog.c 16: printf("Enter the previous month meter reading:");
 prog.c 17: scanf("%d",&pmr);
 prog.c 18: nu=cmr-pmr;
 prog.c 19: if(type=='d')
 prog.c 20: bill=nu*3.75;
 prog.c 21: else if(type=='c')
 prog.c 22: bill=nu*6.80;
 prog.c 23: else if(type=='i')
 prog.c 24: bill=nu*12.50;
 prog.c 25: else
 prog.c 26: bill=nu*0.50;
 prog.c 27: printf("Number of units consumed %d",nu);
 prog.c 28: printf("\nTotal bill %f",bill);
 prog.c 29: return 0;
 prog.c 30: }

If the tariff changes in future then replacement text of macros may be changed without changing the code in the program.

Defining a word as macro

A word can be defined as macro. It is mostly done to improve the readability and understandability of program.

Example:


#define out printf
#define in scanf
#include<stdio.h>
int main()
{
 int x,y,z;
 out("Enter two numbers:\n");
 in("%d%d",&x,&y);
 z=x+y;
 out("Sum=%d",z);
 return 0;
}

Execution:
Enter two numbers:
6
9
Sum=15

Example explained:

Show Expanded Source

 prog.c 4: int main()
 prog.c 5: {
 prog.c 6: int x,y,z;
 prog.c 7: printf("Enter two numbers:\n");
 prog.c 8: scanf("%d%d",&x,&y);
 prog.c 9: z=x+y;
 prog.c 10: printf("Sum=%d",z);
 prog.c 11: return 0;
 prog.c 12: }

The preprocessor replaces “printf” in place of “out” and “scanf” in place of “in” before compilation of program.

Defining a part of program as macro

A statement or number of statements can be defined with a macro.

Example:


#define B int main()
#define C }
#include<stdio.h>
B
{
 printf("Hello world");
 return 0;
C

Output:
Hello world

Example explained:

Show Expanded Source

 prog.c 4: int main()
 prog.c 5: {
 prog.c 6: printf("Hello world");
 prog.c 7: return 0;
 prog.c 8: }

Here B is replaced with int main() and C is replaced with } by the preprocessor before compilation.

Example:

#define B int main()\
          {
 #define C return 0;\
           }
 #include<stdio.h>
 B
 printf("Hello world");
 C

Output:
Hello world

Example explained

Show Expanded Source

 prog.c 6: int main() {
 prog.c 7: printf("Hello world");
 prog.c 8: return 0; }

Here multiple statements are defining as macro.\ is used to extend a line.

Previous post:

Next post: