The greatest mistake you can make in life is to be continually fearing you will make one

Tuesday 2 March 2010

C Preprocessor-2

2.File Inclusion(#include):
  • This directive allow one file to be included in another file.
  • Syntax is  #include "file name"
    This will insert the entire content of filename in to the source code.
  • It can be used in 2 cases


    1. If the program is very large then the code is divided in to several different files.These files are #included at the begining of main program file.
    2. Some functions or some macros are almost needed in all programs. These functions and macros are stored in a file and included in the program that are needed Eg header files
  • #include statement can be written in 2 ways


    1. #include "filename"
    2. #include < filename >
  • #include "filename.c" would look for the file filename.c in the current directory as well as the specified list of directories as mentioned in the include search path.
  • #include < filename.c > would look for the file filename.c in the specified list of directories only.
3.Conditional Inclusion
  • It is possible to control preprocessing itself with conditional statements that are evaluated during preprocessing.
  • provides a way to include code selectively depending on the condition.
  • Some of the conditional directives are

    1. #if
    2. #elif
    3. #else
    4. #endif
    5. #ifdef
    6. #ifndef
    7. #undef
  1. #if directive


    • #if can be used to test whether an expression evaluates to a nonzero value or not.(the expression may not include sizeof,casts or enum constants)
    • The generalized form of the if directive is
      #if < condition >
      #endif
    • If the result of the expression is nonzero then subsequent lines upto #endif are compiled otherwise they are skipped.
    • example code to make sure that the contents of the file hdr.h are included only once
      #if !defined(HDR)
      #define HDR
      /* contents of hdr.h */
      #endif
    • The defined() predicate returns true if the symbol is defined otherwise it is false.
  2. #else directive


    • #else always comes with #if directive
    • It allow us to specify the action if the condition is not true
    • Eg: Suppose we have 3 files
      file1.h
      #define USD 1
      file2.h
      #define UKP 1
      file3
      #include < stdio.h >
      #include < file1.h >
      #if(defined(USD))
          #define rate 46
      #else
          #define rate 100
      #endif

      since USD is defined in file1.h,the currency rate is taken as 46.
  3. #elif directive


    • #elif allow us to take one action if there are multiple decision points.
    • #elif is similar to #else but it is followed by a condition.
    • Example: The following sequence tests the name SYSTEM to decide which version of a header to include

      #if SYSTEM == SYSV
          #define HDR "sysv.h"
      #elif SYSTEM == BSD
          #define HDR "bsd.h"
      #elif SYSTEM == MSDOS
         #define HDR "msdos.h"
      #else
          #define HDR "default.h"
      #endif
      #include HDR
  4. #ifdef directive


    • The ifdef directive makes substitution based on whether a particular identifier is defined.
    • If the identifier is defined,it returns true,otherwise it is false.
    • Eg: Suppose we have 3 files
      file1.h
      #define USD 1
      file2.h
      #define UKP 1
      file3
      #include < stdio.h >
      #include < file1.h >
      #ifdef USD
          #define rate 46
      #endif
      #ifdef UKP
          #define rate 100
      #endif
      The 1st ifdef directive checks whether the identifier USD is defined. since it is defined in file1.h the condition is true and the rate is defined as 46. The 2nd ifdef directive checks whether the identifier UKP is defined.Since file2.h is not included it is not defined so the condition is false and the directive is not processed.
      If instead of file1.h, if file2.h is included then the rate will be 100 
  5. #ifndef directive


    • #ifndef (means 'if not defined') works exactly opposite to #ifdef.
    • #ifndef is compleement of #ifdef. so when #ifdef returns true,#ifndef returns false
    • Eg: Suppose a function fun() is defined in a file 'file1.h'.and file1.h is #included in file2.h.now if we #include both 'file1.h' and 'file2.h' then the compiler flashes an error 'multiple declaration for fun'.To avoid this we can write the following code in the header file
      /*file1.h*/
      #ifndef file_h
          #define file_h
          fun()
          {
              /*code*/
          }
      #endif
    • first time the file 'file.h' gets included the preprocessor checks whether a macro called file_h has been defined or not.first time its not defined so the macro gets defined and the fun() get included.Next time we attempt to include the same file.the macro file_h already defined so the fun() is not included.
  6. #undef directive


    • #undef nullify the effect of the #define directive and specify a new value.
    • Ex:
      #include < stdio.h >
      #define SUM 40
      #undef SUM
      #define SUM 100
      int main()
      {
      printf("SUM=%d\n",SUM);
      }
      The 1st #define assign SUM as value 40 but the #undef indicate that the SUM definition no longer exist. The 2nd #define define SUM as 100. so the program will print the output as SUM=100.
4.Miscellaneous Directives
  • There are 3 more preprocessor directives available but they are not very commonly used
  1. #pragma
  2. #error
  3. #line
1.#pragma directive:
  • #pragma is a special purpose directive that can use to turn on or off certain features
  • pragmas vary from one compiler to another.
  1. #pragma startup and #pragma exit: These directives allow us to specify functions that are called upon program startup(before main()) or program exit(just before the program terminates)
    Ex:
    void myfun1();
    void myfun2();
    #pragma startup myfun1
    #pragma exit myfun2
    int main()
    {
        printf("I am in main\n");
        return 0;
    }
    void myfun1()
    {
        printf("I am in myfunction1");
    }
    void myfun2()
    {
        printf("I am in myfunction2");
    }
    Output
    I am in myfunction1
    I am in main
    I am in myfunction2
    Note1.The functions myfun1() and myfun2() will not receieve or return any value.
        2.If we want 2 functions to executed at startup then thier pragmas should be defined in the reverse order in which we want to call them
  2. #pragma warn: This directive tells the compiler whether or not we want to suppress a specific warning
    Eg:
    #pragma warn -rvl /*return value */
    #pragma warn -par /*parameter not used*/
    #pragma warn -rch /*unreachable code*/
    int fun1()
    {
        printf("I am in function1");
    }
    void fun2(int a)
    {
        printf("I am in function2");
    }
    int fun3()
    {
        int z=10;
        return z;
        z++;
    }
    int main()
    {
        fun1();
        fun2(100);
        fun3();
        return 0;
    }
    In the above example the function fun1() doesnt return a value. The parameter passed to the fun2() is not being used in fun2() and the control will never reach z++ in fun3()
    If we compile the program we should expect warnings indicating the above problem.
    But the program does not produce warnings because we have suppressed the warnings using #pragma.
     If we replace the '-' sign with the '+' sign in #pragma then the warnings will be shown in the compilation.
 3.#error directive:
  • The error directive is used to specify an error message for a specific situation
  •  The error message is generated by the preprocessor at compile time.
  • Eg:Suppose we have 3 files
    file1.h
    #define USD 1
    file2.h
    #define UKP 1
    file3
    #include < stdio.h >
     #include < file1.h >
    #if !defined(USD) || !defined(UKP)
       #error "ERROR: NO_CURRENCY rate is specified"
    #endif

    #if checks whether USD or UKP is defined.If both are not defined then the preprocessor displays an error
4. #line Directive:
  • The #line directive allows us to define arbitrary line numbers for the source lines.
  • Normally the compiler counts lines starting at line number 1.using the #line directive,we can specify an arbitrary line number at any point.The compiler then uses that line number for subsequent counts.
  • #line is used to indicate line numbers which can be used for debugging
  • Eg:
     
    int main()
    {
         fun1();
      #line100
        fun2(100);
       printf("C FILE %s LINE %d\n",_FILE_,_LINE_);
       #line200
        fun3();
        return 0;
     }
     after fun1() the line number is assigned to 100. so fun2(100); is at line number 101 and then line number is modified to 200 before fun3();. so fun3(); is at line number 201.
  • _FILE_ and _LINE_ are the 2 special identifiers.Which indicate the file name of the source file and the current line number 

No comments:

Post a Comment