Inroduction To PreProcessors


Inroduction To PreProcessors

Inroduction To PreProcessors
INTRODUCTION:
    The C preprocessor is a program that processes our source program before it is passed to the compiler.This is a  capability that does not exist in many other higher level
languages.

FEATURES OF C PREPROCESSOR:
     The C program involves so many stages from the stage of writing C program  to the stage of getting it executed.

  The processors used in the execution of C program are
        1.Text Editor
        2.Preprocessor
        3.Compiler
        4.Linker
PreProcessor Directives


There  are four types of preprocessor directives,these are shown below.

Preprocessor directives are:
1. Macro expansion
2. File inclusion
3. Conditional Compilation
4. Miscellaneous directives


EXPLANATION FOR PREPROCESSOR DIRECTIVES:

1.MACRO EXPANSION:
      consider the example given below
  #define UPPER 25
  main()
  {
         int i;
         for(i=1;i<=UPPER;i++)
         printf("\n%d",i);
  }
  from the above example it is known that instead of writing 25 in the for loop we are writing it in the form of UPPER,which is already defined before main() through the statement,
#define UPPER 25
  The above statement is called ‘macro definition' or ‘macro'.The purpose of this macro in the program is it replaces every occurrence of UPPER in the program with 25 during the time of
preprocessing.
        Example for macro definition:
                  #define PI 3.1415
                  main()
                 {
                    float r=6.25;
                    float area;
                    area=PI*r*r;
                    printf("\n Area of Circle=%f",area);
                 }
 from the above program  UPPER and PI are called ‘macro templates', and the 25 and 3.1415 are called their corresponding ‘macro expansions'.

  Explanation:
  At the time of compilation of program, before the source code passes to the compiler  is examined by the C preprocessor for any macro definitions. When it sees the #define directive,it goes through the entire program in search of the macro templates. Where ever it finds one, it replaces the macro 
template with the appropriate macro expansion. Only after the completion of this procedure the program handed over to the compiler.
  
Note:
   it needs space between macro template and its macro expansion that is separated by blanks or tabs. A space between # and define is optional. A macro definition never terminated by semicolon.

 Use: use of  #define in the program makes easy to read. That is it makes easy to recognize constants. For example substituting PI for 3.1415 makes the program to read easier.Here it is easy to recognize the constant 3.1415. but there are many instances where a constant doesn't reveal its purpose. For example the phrase "\x1B[2J" causes the screen to clear. But it is easier to understand this in the middle of program when we use "CLEARSCREEN" as the macro template & "\x1B[2J" as the macro expansion. therefore the macro definition for this is

  #define CLEARSCREEN "\x1B[2J"   it shows that where ever  CLEARSCREEN appears in the 
program it would automatically be replaced by "\x1B[2J" before compilation begins.In short, it is nice to know that it is able to change values of a constant at all places in the program by just making a change in the #define directive.

Conclusion:
     thus using #define can produce more efficient and more easily understandable programs. It is used extensively by C programmers.

Some examples of using #define directive:
1.A #define directive is mainly a times used to define 
operators as shown below.
            #define AND &&
           #define OR ||
           main()
         {
             int f=1,x=4,y=90;
              if((f<5) AND (x<=20 OR y<=45))
              printf("\n Your PC will always work fine");
              else
              printf("\n In front of the maintenance man");
         }

2. A #define directive could be used even to replace a 
condition, as shown below.
        #define AND &&
        #define ARANGE(a>25 AND a<50)
        main()
      {
        int a=30;
       if(ARANGE)
              printf("within range");
       else
             printf("out of range");
      }

3. A #define directive could be used to replace even an 
entire C statement. This is as shown below.

        #define  FOUND printf("The Yankee diode virus");
        main()
        {
             char signature;
               if(signature=='Y')
                   FOUND
               else
                    printf("safe");
        }

Macros also consists of arguments.
Macros with arguments:

Macros can have arguments same as functions. example below shows how the arguments are used within macros.

                #define AREA(x) (3.14*x*x)
                main()
               {
                    float r1=6.25, r2=2.5,a;
                    a=AREA(r1);
                     printf("\n area of circle is=%f",a);
                   a=AREA(r2);
                   printf("\n area of circle=%f",a);
               }
   In this program wherever the preprocessor finds phrase AREA(x) it expands it into the  statement (3.14*x*x). here  the x in the macro template AREA(x) is an argument this one matches the x in the macro expansion (3.14*x*x). The statement AREA(r1) in the program causes the variable r1 to
be substituted for x. Thus the statement AREA(r1) is 
equivalent to 
             (3.14*r1*r1)
    After the passing of source code through the preprocessor, compiler works on

                   main()
                   { 
                    float r1=6.25,r2=2.5,a;
                    a=3.14*6.25*6.25;
                    printf("Area of circle=%f\n",a);
                    a=3.14*2.5*2.5;
                    printf("Area of circle=%f",a);
                   }
The output of this  program after the completion of whole process is as shown below.. 
    Area of circle is=122.656250
    Area of circle=19.625000

  example 2:
                     #define ISDIGIT(y) (y>=48 && y<=57)
                     main()
                    {
                     char ch;
                     printf("Enter any digit");
                     scanf("%c",&ch);
                     if(ISDIGIT(ch))
                           printf("\n digit is entered");
                     else
                         printf("\n illegal input");
                    }
   macros with arguments should consider the following 
conditions.

1.At the time of defining the macro there should not be blank  between macro template and its argument. for example in the above program there  should not be blank between AREA and (x)
in the definition. i.e #define AREA(x) (3.14*x*x)   if  AREA  (x)  is written instead of AREA(x) it causes to  some problems. i.e (x) becomes the part of macro expansion this leads to expand macro as shown below. This statement  won't run.
        (6.25) (3.14*6.25*6.25)

2. The entire macro expansion should enclosed within parentheses. Here is an example for enclosing the macro within parentheses.  This shows the problems occurred if macro is not enclosed within the parentheses.

           #define SQUARE(n) (n*n)
           main()
         {
            int j;
            j=64/SQUARE(4);
            printf("j=%d",j);
         }
         
 The output for this program we will get as j=64  instead of j=4 because in the above program as the macro is not enclosed within the parentheses it is expanded as 
                j=64/4*4;
       which gives output as 64.

The second preprocessor directive is File Inclusion    .

2. FILE INCLUSION:
  
 This directive causes one file to be included in another. The preprocessor command for File Inclusion is
                #include "filename"

 this command inserts the entire contents of filename into the source code at that point in the program. This File Inclusion preprocessor is used in two cases they are

1. If the program is very large the code is divided into several different files,each containing a set of related functions these File Inclusion preprocessor is used. These files are included at the beginning of  main program file.

2.functions or macro definitions are needed in many programs commonly. In such situations these commonly used functions and macro definitions are stored in a file, and that file can be included in every program. This will add all the statements in this file to program which is written.   In programs generally files are included with the extension .h, this extension stands for 'header file'. It contains 
statements which when included go to the head of program.There are two ways to write #include statement.
 They are:
        #include "filename"
        #include 
 The difference between these two statements is as shown 
below.
#include "goto.c" :
        This command look for the file goto.c in the current 
directory as well as the specified list of directories as 
mentioned in the include search path which have been setup.

#include :
        This command would look for the file goto.c in the 
specified list of directories only.

The third type of preprocessor directive is  Conditional 
Compilation.

3.CONDITIONAL COMPILATION:

    This Conditional Compilation is used when the compiler 
skip over part of a source code by inserting the processing
commands. These processing commands are  #ifdef and #endif.
 The general form of these processing commands is as shown 
below.

       #ifdef macro name
              statement 1;
             statement 2;
            statement 3;
      #endif
                          
    If the macro name has been #defined, the block of code 
will be processed as usual otherwise the block of code will
not processed as usual.

 ifdef processing command can be used in two cases. They are:

1.To "comment out" obsolete lines of code. This often occurs
 that a program is changed at the last minute to satisfy a 
client. This involves rewriting some part of source code to 
the client's satisfaction and delete the old code. But if the
client again needs the old code it is difficult to rewrite the
old code in the place of new code.
      To overcome this problem the old code can be kept in 
comments i.e /*        */ combination. But if we have already
written a comment in the code that about to "comment out".
This would mean to end up with nested comments. i.e in C we 
can't nest comments. Therefore solution for this is to use 
conditional compilation as shown below.
   main()
  {
   #ifdef OKAY
         statement 1;
         statement 2;             /* detects virus*/
        statement 3;
       statement 4;            /* specific to stone virus */
  #endif
            statement 5;
            statement 6;
           statement 7;
       }
                  
   In the above program the statements 1,2,3&4 can be compiled only if the macro OKAY has been defined. If all these statements have to get compiled it needs to delete the #if def  and #end if statements.

2.#ifdef can be used mostly to make the programs portable. i.e. to make work on two totally different computers so that it needs to write a program that works on both machines. For this it needs to isolate the lines of code that must be different for each machine by marking them off with #ifdef.
      Example for this is
        main()
       {
         #ifdef PCAT
               code suitable for a PC/AT
        #else
              code suitable for a PC/XT
       #endif
      code common to both the computers
    }
            
 After the compilation of this program it would compile only the code suitable for a PC?XT  and the common code. This occurs because the macro PCAT has not been defined. Working of #if def - #else - #endif is similar to the ordinary if-else control instruction of C.

In this program if the program wants to un on PC/AT, it is needed to add the statement    
             #define PCAT   in the program.

 #ifndef directive can be used in the place of 
#ifdef in some situations.
 The #ifndef  i.e'if not defined' works exactly opposite to #ifdef.

        Example for this is as shown below.

       main()
      {
            #ifndef PCAT
                code suitable for a PC/XT
           #else
               code suitable for a PC/AT
          #endif
              code common to both computers
   }

   After compilation of this program it gives the output as code suitable for a PC/AT and the common code. i.e exactly opposite to the #ifdef statement.

         #if  and #elif  Directives:

 The #if directive can be used to test whether an expression evaluates to a nonzero value or not. If the result of the expression is nonzero, then subsequent lines upto a #else, #elif or #endif are compiled, otherwise they are skipped. A simple example of #if directive is as shown below.
                   Main()
                 {
                   #if TEST<=5
                          statement 1;
                         statement 2;
                        statement 3;
                  #else
                      statement 4;
                     statement 5;
                     statement 6;
               #endif
            }
                   
 In the above program if the expression, TEST<=5 evaluates to true then statements 1,2,and 2 are compiled otherwise statements 4,5 and 6 are compiled. In place of the  expression TEST<=5 other expression like (LEVEL==HIGH || LEVEL==LOW) or ADAPTER==CGA can also be used.

Nested conditional compilation is also possible. The example below shows such directives.
              #if ADAPTER==MA
                   code for monochrome adapter
             #else
                   #if ADAPTER==CGA
                     code for colour graphics adapter
           #else
                  #if ADAPTER==EGA
                    code for enhanced graphics adapter
                #else
                #if ADAPTER=VGA
                     code for video graphics array
               #else
                     code for super graphics array
              #endif
             #endif
           #endif
        #endif

    This program also can be made more compact by using another conditional compilation directive called #elif. The same program using this directive can be written as shown below. Use of #elif in this program reduces the no of end ifs.

                #if ADAPTER==MA
                       code for monochrome adapter
              #elif ADAPTER==CGA
                      code for colour graphics adapter
             #elif ADAPTER==EGA
                     code for enhanced graphics adapter
           #elif ADAPTER==VGA
               code for video graphics array
          #else
                   code for super video graphics array
         #endif

       The fourth one preprocessor Directives is Miscellaneous  Directives.

4) MISCELLANEOUS IRECTIVES:

There are two more preprocessor directives are used . They are 

1.#undef
2.#pragma

#undef Directive:
    This directive is used to undefine the directive if it is already defined. i.e if the statement is already used the directive #define to define the directive to undefine 
this #undef is used.

   The #undef command id
          #undef macro template
   statement for this is
        #undef PCAT
  
this statement causes the definition of PCAT to be removed from the system. All subsequent #ifdef PCAT statements would evaluate to false.

#pragma Directive:
This directive is one special directive that is used to turn on or off certain features. programs vary from one compiler to another. There are certain programs available with Microsoft C compiler which deal with formatting source listings and placing comments in the object file generated by the compiler. Turbo C compiler has the pragma which allows to write assembly language statements in C program.

No comments:

Post a Comment