Header Ads

3.6 - Preprocessors

Preprocessor
  • One of the step performed before compilation
  • Is a text substitution tool and it instructs the compiler to do required pre-processing before the actual compilation
  • Instructions given to preprocessor are called preprocessor directives and they begin with “#” symbol
  • Few advantages of using preprocessor directives would be,
  • Easy Development
  • Readability
  • Portability
  • Preprocessor – Compilation Stages

  • Before we proceed with preprocessor directive let's try to understand the stages involved in compilation. 
  • Some major steps involved in compilation are
    • Preprocessing (Textual replacement) 
    • Compilation (Syntax and Semantic rules checking) 
    • Assembly (Generate object file(s)).
    • Linking (Resolve linkages) 
    The below image provides the flow of these stages.     
  • Preprocessor – Directives

    #include                   #elif
    #define                    #error
    #undef                     #warning
    #ifdef                     #line
    #ifndef                    #pragma
    #else                      #
    #endif                     ##
    #if 
    #else 
    • Preprocessor – Header Files

  • A header file is a file containing C declarations and macro definitions to be shared between several source files. 
  • Has to be included using C preprocessing directive ‘#include' 
  • Header files serve two purposes:
    • Declare the interfaces to parts of the operating system by supplying the definitions and declarations you need to invoke system calls and libraries.
    • Your own header files contain declarations for interfaces between the source files of your program.
  • Preprocessor – Header Files vs Source Files

  
● Declarations                                 ● Function and variable definitions
● Sharable/reusable                        ● Non sharable/reusable
        ● #defines                                         ● #defines
        ● Datatypes                                       ● Datatypes
● Used by more than 1 file
 
Preprocessor – Header Files - Syntax
Syntax
#include <file.h>
  • System header files 
  • It searches for a file named file in a standard list of system directories
#include “file.h”
  • Local (your) header files
It searches for a file named file first in the directory containing the current file, then in the quote directories and then the same directories used for <file>
Header Files – Search Path
  • On a normal Unix system GCC by default will look for headers requested with #include <file> in:
    /usr/local/include
    libdir/gcc/target/version/include
    /usr/target/include
    /usr/include 

You can add to this list with the -I command-line option 

“gcc -print-prog-name=cc1 -v” would search the path info 

Header Files – Once-Only
  • If a header file happens to be included twice, the compiler will process its contents twice causing an error
    • E.g. when the compiler sees the same structure definition twice, This can be avoided like:
Example:
#ifndef NAME
#define NAME
/* The entire file is protected */
#endif

Macro – Object-Like
  • An object-like macro is a simple identifier which will be replaced by a code fragment 
  • It is called object-like because it looks like a data object in code that uses it. 
  • They are most commonly used to give symbolic names to numeric constants
Syntax
#define SYMBOLIC_NAME   CONSTANTS
Example
-------
#define BUFFER_SIZE     1024

Macro – Arguments
  • Function-like macros can take arguments, just like true functions
  • To define a macro that uses arguments, you insert parameters between the pair of parentheses in the macro definition that make the macro function like
Example
#include 
#define SET_BIT(num, pos)  (num | (1 << pos))
int main()
{
     SET_BIT(0, 2);
     return 0;
}

Macro – Multiple Lines
  • You may continue the definition onto multiple lines, if necessary, using backslash-newline.
  • When the macro is expanded, however, it will all come out on one line
Example
    #include 
    #define SWAP(a, b)         \
    {                          \
    int temp = a;              \
    a = b;                     \
    b = temp;                  \
    }
    int main()
    {
    int num1 = 10, num1= 20;
              SWAP(num1, num2);
              printf(“%d %d\n”, num1, num2);
    } 


Macro – Standard Predefined
  • Several object-like macros are predefined; you use them without supplying their definitions.
  • Standard are specified by the relevant language standards, so they are available with all compilers that implement those standards
Example
#include 
int main()
{
         printf(“Program: \“%s\” ”, __FILE__);
         printf(“was compiled on %s at %s. ”, __DATE__, __TIME__);
         printf(“This print is from Function: \”%s\” at line %d\n”, __func__, __LINE__);
    return 0;
}

Preprocessor – Conditional Compilation
  • A conditional is a directive that instructs the preprocessor to select whether or not to include a chunk of code in the final token stream passed to the compiler
  • Preprocessor conditionals can test arithmetic expressions, or whether a name is defined as a macro, or both simultaneously using the special defined operator
  • A conditional in the C preprocessor resembles in some ways an if statement in C with the only difference being it happens in compile time 
  • Its purpose is to allow different code to be included in the program depending on the situation at the time of compilation. 
  • There are three general reasons to use a conditional.
    • A program may need to use different code depending on the machine or operating system it is to run on 
    • You may want to be able to compile the same source file into two different programs, like one for debug and other as final 
    • A conditional whose condition is always false is one way to exclude code from the program but keep it as a sort of comment for future reference
Conditional Compilation - ifdef
Syntax
#ifdef MACRO
            /* Controlled Text */
#endif
Conditional Compilation - defined
Syntax
#if defined (ERROR) && (WARNING)
    /* Controlled Text */
#endif

Conditional Compilation - if
Syntax
#if expression
    /* Controlled Text */
#endif

Conditional Compilation - else
Syntax
#if expression
         /* Controlled Text if true */
#else
         /* Controlled Text if false */
#endif

Conditional Compilation - elif
Syntax
#if DEBUG_LEVEL == 1
          /* Controlled Text*/
#elif
DEBUG_LEVEL == 2
          /* Controlled Text */
#else
          /* Controlled Text */
#endif
Preprocessor – Diagnostic
  • The directive ‘#error’ causes the preprocessor to report a fatal error. The tokens forming the rest of the line following ‘#error’ are used as the error message
  • The directive ‘#warning’ is like ‘#error’, but causes the preprocessor to issue a warning and continue preprocessing. The tokens following ‘#warning’ are used as the warning message

...

No comments