Wednesday, January 18, 2012

Preprocessors


Preprocessors
Preprocessors is a program that modifies the C++ source program according to directives supplied in the program. The original source program is usually stored in a file. The preprocessors does not modify this program file, but creates a new file that contains the processed version of the program. This new file is then submitted to the compiler. The processor makes the program easy to understand and port it form one platform to another. A preprocessor carries out the following actions on the source file before it is presented to the complier. These actions consists of
·        replacement of defined identifiers by pieces of the text
·        conditional selection of parts of the source file,
·        inclusion of other files, and
·        renumbering of source files and renaming of the source files itself.
The general rules for defining a preprocessor are:
(a)    All preprocessors directives begin with the sharp sign (#).
(b)    They must start in the first column and on most C++ compiler there can be no space between the number sign and the directive.
(c)    The preprocessors directive is terminated not by a semicolon.
(d)    Only one preprocessor directive can occur in a line.
(e)    The preprocessors directives may appear at any place in any source file: outside/inside functions or inside compound statements.
 The C++ preprocessor is a simple macro processor that conceptually processes the source text of a C++ program before the compiler parses the source program. The preprocessor is controlled by special preprocessor command lines, which are lines of the source file beginning with the character’#’. Note that character ‘#’ has no other use in the C++ language.
    The Common C++ preprocessor directives and their uses are:
  DIRECTIVE    
         USES
#include

#define

#undef

#if

#ifdef

#ifndef

#else

##elif

#endif

#line

#error
insert text from another file

defined preprocessor macro

remove macro definitions

conditionally include some text based on the value of the constant expression

conditionally include some text based on predefined macro name

conditionally include some text with the sense of the test opposite to that of#ifdef
alternatively include some text, if the previous #if,#ifdef,or#ifndef tests failed
combination of #if and #else

terminate conditional text

give a line number for compiler massages

terminate processing early


4.11.1 Simple Macro Definitions
A macro is simply a substitution string that is placed in a program.
For example , consider the following program segment,
#defined MAX 100
void main ( )
{
    char name [MAX];
    for ( i=0; i<= MAX-1; ++i)



               
    }
which is internally replaced with the following program
void main ( )
{
    char name [100]
    for (i=0; i<= 100-1; ++i)


           
   }
and subsequently compiled. Each occurrence of the identifier MAX as a token is replaced with the string 100 that follows the identifier in the #defined line.
    The simple from of macro is particularly useful for introducing named constants into a program. This makes it easier to change the number later.
    For example, the following are valid #defined statements.
          #define TRUE 1
          #define FALSE 0
          #define EOF -1
          #define SIZE 5
          #define TRACK_SIZE 6
          #define MAX_BLOCK 100
    The syntax of the #define command does not require an equal sign or any other special delimiter token after the name begin defined.
    Some invalid #defined statements are illustrated below.
(1)
      #define SIZE = 3
   The #define statement is used to merely substitute the string constants into the source program.
    For example,
       #define SIZE =3
       #include <iostream.h>
       void main ( )
       {
              int value [SIZE];
              for (i=0; i<= SIZE-; ++i)


                      
       }
   The macro substitutes every occurrence of the SIZE with the =3, modifying the above source program as,
     #include <iostream.h>
     void main ( )
     {
          int value [=3];       // syntax error
          for (i=0; i<= =3-1; ++i)        // syntax error


                
     }
    (2) The #define statement does not take the semiclone.
          #define MAX 100;  //error
For example,
          #define Max 100;
          #include <iostream.h>
          void main ( )
          {
               char name [MAX];
               for (i = 0; I <= MAX-1; ++i)


               
          }
  The macro substitutes every occurrence of the MAX with the 100; modifying the above program segment ,as,
      #include <iostream.h>
     void main ( )
    {
         char name [100;];  // syntax error
         for (i =0; i <= 100;-1; ++ i) // syntax error


         
    }

Macro with Parameters
A more complex from of a macro definition declares the names of formal parameters within parentheses, separated by commas.
           #defined name (variable 1,variable2...variable n) substitution_string
For example,
    #define PRODUCT(x,y) ( (x) * (y) )
    #define max (x,y) ((x) > (y) ? (x) : (y))
    #define min (x,y) ((x) < (y) ? (x) : (y))
  Macros operator purely by textual substitution of tokens. The C++ compiler parses the source program only after the completion of the macro expansion processes are completed. Hence, care must be taken to get the desired result.
   For example,
        #define PRODUCT (x) x*x
  If we call this macro definition in the C++ program,
   #define PRODUCT (x) x*x
   void main ()
   {
      PRODUCT (10) ; 


               
    }
   PRODUCT (10) expends 10*10. However, the expression
   PRODUCT (a+1) expands to a+1*a+1
    When the above expression is executed, it is interpreted as a+(1*a)+1 because the multiplication has higher precedence over the addition. This will not produce the same result as (a+1) * (a+1) unless a happens to be zero. It would be somewhat safer to put parentheses around occurrences of the formal parameters in the definition of PRODUCT as,
     #define PRODUCT (x) (x) *(x)
     Even this definition does not provide the complete protection against precedence problems.
     For example,
        #define PRODUCT (x) (x)* (x)
      #include <iostream.h>
      void main ()
      {
           (short) PRODUCT ( a+1)


            
      }
      The preprocessor substitutes the macro as
       (short) (a+1) * (a+1)
        then, it would be parsed as
       ((short) (a+1)) * (a+1)
       as a cast has higher precedence over multiplication. Hence proper parentheses should be used within the macro definition statement to get the desired result. The correct way of defining the PRODUCT macro is
      #define product (x) ((x) * (y))
Other Preprocessing Techniques
As the preprocessor merely substitutes a string of text for another without any checking, a wide variety of substitutions are possible and hence, it is possible to make any typed source program look like another language. To illustrate the above, if someone has a strong linking for Pascal and its syntax, then many Pascal symbols can be used in C++ symbols before the compilation.
   For example,
         /* pascal.h */
       #define     begin      {
       #define     end         }
       #define     writeln    printf
       #define     mod        %
       #define     div          /
       #define     program  main
       #define     integer    int
       #define     var          /* variable declaration */

PROGRAM
A program define the Pascal syntax in a C++ program using a macro declaration.
    #include <stdio.h>
   #include <pascal.h>
   program ()
   begin
        writeln (“Pascal output|n” );
   end

PROGRAM
A program to include the header file in a C++ program.
   #include <stdio.h>
   #include <pascal.h>
   var
   integer a,b,c;
   program ()
   begin
   a + 10;
   b + 20;
   writeln ( “%d + %d = %d\n” ,a,b,c);
   end

PROGRAM
A program for microprocessor simulator using the macro definition.
    #define SWAP (x,y,type)
   {type temp; temp= (x) ; (x) = (y) =temp; }
    #define MOV (d,s)                (d) = (s);
    #define ADD (d,s)                (d) = (d) + (s);
    #define MUL (d,s)                (d) = (d)*(s); /* s – source */
    #define DIV (d,s)                 (d) = (d) /(s); /* d – destination */
    #define XCHG (d,s)              SWAP (d,s, SWAPTYPE);
    #define OUT (value)             printf (“%d”, (value));
    #define OUTB (value)           printf (“%c”, (value));
    #define OUTS (label)            printf (“%s”, (value));
    #define LF                          printf (“\n”);
    #define ASCII (label, string)  char *label +{ string};
    #define WORLD (label)         int label;
    #define BYTE (label)            char label;
    #define START                    main () {
    #define END                       }
    #define SWAPTYPE          int
   ASCII (msg, “Microprocessor simulator “)
   START
   WORLD (result)
   WORD (r1)
   WORD (r2)
   MOV    ( result ,0)
   MOV    ( r1 ,20)
   MOV    ( r2,20)
   MOV    ( result ,r1)
   ADD    ( result ,r2)
   LE
   OUTS  ( “ Sum of = “)
   OUT    ( result)
   LE
   MOV    ( result ,r1)
   MUL    ( result ,r2)
   OUTS    ( “Multiplication of =”);
   OUT    (result )
   LE
   MOV    ( result ,r1)
   DIV     ( result ,r2)
   OUTS    ( “Division of =”)
   OUT      ( result)
   END

Conditional Compilation
The processor conditional compilation commands allow lines of the source text to be passed through or eliminated by the preprocessor on the basis of a computer condition.
    The following are the preprocessor conditional commands.
           #if
         #else
         #endif
         #elif
The above commands are used in the following way:
         #if constant expression
              group of lines 2
         #else
              group of lines 2
         #endif
   A group of lines may contain any number of lines of the text or any kind, even other preprocessor command lines, or no lines at all. The #else command may be omitted.
The #elif command  The #else command is fairly a recent addition to C++. It is supported by very few compilers only. The #elif command is like a combination of #if and #else. It is used between #if and #endif in the same way as #else but has a constant expression to evaluate in the same way as #if.
It is used in the following format
      #if constant expression
            group of lines 1
      #elif constant expression
            group of lines 2
      #elif constant expression
            group of lines 3


                  
      #else
           group of lines n
      #endif
The same commands can be written using #if, #else and #endif.
For example,
      #if expression


      
      #elif expression


      
      #elif expression


     
      #else


      
      #endif
  In case a part particular is not supporting the #elif conditional command, Then the above commands may be modified as:
      #if expression


      
      #else
      #if expression


      
      #else
      #if expression


       
      #else


      
      #endif
      #endif
      #endif

No comments:

Post a Comment