Tutorial Study Image

C++ preprocessor


June 13, 2023, Learn eTutorial
281

One of the special aspects of C++ is preprocessor directives. It offers numerous facilities which other high-level languages can not, as well as programmers can utilize these tools to construct C ++ programs that are effective, simple to read, simple to edit, and portable.

The compiler processes the source code just before the compiler compiles a C++ program. Preprocessor is the name of the technique while preprocessing is the name of the operation. It is a kind of separate program section that is called by the C++ compiler in the very first part of the translation. This procedure falls inside the compilation process but is not a component of the compiler. It instructs the compiler to preprocess the data before beginning the compilation process.

Since this is not a statement in C++, all preprocessor directives in that language start with # and do not need to conclude with a semicolon (;).

A symbolic constant is created via the #define directive, and these symbolic constants are usually referred to as macro.

The directive in its most general form is:


#define macro-name replacement-text
 

A basic C++ preprocessing directives program


#include<iostream> 
#define val 100

using namespace std;

int main()
{
    cout << "Value will be :" << val << endl;
}

 

Output:


Value will be :100

Various preprocessor directives carry out various functions. These Preprocessor Directives fall under the following categories:

Inclusion Directives: Macro Definition Directives: Conditional Compilation Directives: Other Directives

#include: 

defines the files that should be included, particularly header files.

·#define: it mainly specifies a macro substitution.

 

·#undef:Undefining a macro is accomplished using it.

·#if:It examines a compile-time condition.

 

·#endif:It indicates where #if ends.

 

·#ifdef:The macro definition is tested using this.

·#ifndef:If a macro is not defined, it is tested.

·#else:When #if fails, it offers an alternate choice.

· #error:

· #line:a line number is provided for compiler messages.

·#pragma:It gives the compiler instructions that are defined by the implementation.

The Four Major Categories of Preprocessor Directives are:

  • Macros
  • File Inclusion
  • Conditional Compilation
  • Other directives
  1. Macros

    In a program, there are named sections of code called macros. When the compiler comes across this term, it switches out the name for the actual piece of code. A macro is defined using the '#define' directive. Let us use a program to understand the definition of a macro now:

    Program using macros

    
    #include <iostream>
    
    // macro definition
    #define LIMIT 6
    int main()
    {
     for (int i = 0; i < LIMIT; i++) {
      std::cout << i << "\n";
     }
    
     return 0;
    }
    
     
    

    Output:

    
    0
    1
    2
    3
    4
    5
    

    When the compiler runs the preceding program, it substitutes the number 6 for the word LIMIT. In the macro definition, the word "LIMIT" is referred to as a macro template, while the number "6" is a macro expansion.

    The macro definition ends without a semicolon (;). A semicolon is not required to finish macro definitions.

    Macros with Arguments: Macros also accept arguments. Function-like behavior is shared by macros defined with arguments. Let's examine this using a program:

    Program for macros with arguments

    
    #include <iostream>
    
    // macro with parameter
    #define AREA(l, b) (l * b)
    int main()
    {
     int l1 = 20, l2 = 10, area;
    
     area = AREA(l1, l2);
    
     std::cout << "The area of rectangle is: " << area;
    
     return 0;
    }
    
     
    

    Output:

    
    The  area of rectangle is: 200
    

    The program above demonstrates how the compiler substitutes the statement (l*b) whenever it encounters the expression AREA(l, b) in the program. Additionally, the values provided to the macro template AREA(l, b) in the statement (l*b) will be replaced. As a result, AREA(20, 10) will equal 20*10.

  2. File Inclusion

    This kind of preprocessor directive instructs the compiler to add a file to the program's source code. The user can add two different sorts of files to the program:

    Standard files versus header files: The pre-defined functions like printf(), scanf(), and others are defined in these files. For these functions to function, these files must be present. Various functions are declared in various header files. The 'iostream' file has functions that do basic I/O, whereas the'string' file contains functions that handle string operations.

    Syntax:

    
    #include< file_name >
     
    

    where file name denotes the name of the file that should be included. The '<' and '>' brackets will tell the compiler to look in the standard directory for the file.

    User-defined files: It's a good idea to break up a program into smaller files when it gets to be a size that makes it difficult to use it all at once. User-defined files are these kinds of files. You can include these files:

    
    #include"filename"
     
    
  3. Conditional Compilation

    Conditional compilation directives are a sort of directive that can be used to compile or omit to compile a specified section of a program depending on certain criteria. 'ifdef' and 'endif' are two preprocessing instructions that can be used to do this.

    Syntax:

    
    #ifdef macro_name
        statement1;
        statement2;
        statement3;
        .
        .
        .
        statementN;
    #endif
     
    

    If a macro with the name "macro name" is defined, so the block of statements will execute ordinarily; however, if it is not declared, the compiler will skip this block of statements.

  4. Other Directives

    In addition to the two directives mentioned above, there are two others that are rarely used. Which are:

    #undef Directive: A macro can be undefined by using the #undef directive. This command serves as:

    
    #undef LIMIT
     
    

    The existing macro LIMIT will be undefined if this statement is used. Following this one, all "#ifdef LIMIT" statements will evaluate to false.

    #pragma Directive: This special purpose directive is intended to enable or disable certain functionality. These directives are compiler-specific, meaning they differ between compilers. The following are some of the #pragma directives:

    • #pragma startup and #pragma exit: Using the directives #pragma startup and #pragma exit, we may indicate which functions must be executed just before program startup (before control is passed to main()) and just before program exit (before control is returned from main()).

      GCC compilers are incompatible with the program below.

      
      #include <bits/stdc++.h>
      using namespace std;
       
      void func1();
      void func2();
      
      #pragma startup func1
      #pragma exit func2
      
      void func1()
      {
       cout << "Inside the func1()\n";
      }
      
      void func2()
      {
       cout << "Inside the func2()\n";
      }
      
      int main()
      {
       void func1();
       void func2();
       cout << "Inside the main()\n";
      
       return 0;
      }
      
       
      

      Output:

      
      Inside the func1()
      Inside the main()
      Inside the func2()
      

      When run by GCC compilers, the aforementioned code will result in the output seen below:

      Inside the main()

      This occurs as a result of GCC's lack of support for #pragma startup or exit.

    • #pragma warns Directive: The warning message that is displayed during compilation can be hidden using this directive.