C++ Preprocessor And Preprocessor Directives

Last Updated : 21 May, 2026

The preprocessor in C++ is a program that processes the source code before compilation begins. It performs tasks like including header files, macro expansion, and conditional compilation to prepare the code for the compiler.

  • Used to process directives such as #include and #define
  • Helps in code reusability and conditional compilation
  • Generates expanded source code before actual compilation begins

Working of C++ Preprocessor

2056958140
workflow

Above diagram shows the workflow of a C++ program from source code to executable file.

  • Preprocessor checks and processes directives like #include
  • Compiler converts source code into object code
  • Linker combines required files and libraries
  • Final executable file is generated for execution

Preprocessor Directives

Preprocessor directives are special instruction that are given to the preprocessor, which is a part of the compilation process that runs before the actual code is compiled. These directives:

  • begin with the # symbol
  • are processed before compilation
  • do not end with a semicolon (;)

Commonly Used Preprocessor Directives

DirectiveDescription
#includeIncludes header files into the program
#defineDefines macros or symbolic constants
#undefDeletes a macro that has already been defined.
#if / #elif / #else / #endifPerforms conditional compilation
#ifdef / #ifndefChecks whether a macro is defined or not
#errorDisplays a custom compilation error
#warningDisplays a custom warning message
#pragmaProvides compiler-specific instructions

They are mainly used for:

  • including header files
  • defining constants
  • conditional compilation
  • compiler-specific instructions

#include Directive

The #include preprocessor directive is used to include the contents of one file into the current one, use the #include directive. Header files are often included using this directive.

Syntax

Include Standard Header File

#include <header_file>

Include User Defined Header File

#include "header_file"

Note

  • < > searches files from the system library
  • " " searches files from the current directory first

Example:

C++
// Including the standard I/O stream header file
#include <iostream>
using namespace std;

int main() {
    cout << "GeeksforGeeks";
    return 0;
}

Output
GeeksforGeeks

#define Directives

The #define preprocessor directive is used to define macros or symbolic constants in C++. It improves code readability and maintainability by replacing fixed values or code snippets with meaningful names.

Syntax

#define MACRO_NAME value

Example

C++
#include <iostream>
using namespace std;

// Defining macros
#define PI 3.14159
#define findSquare(x) (x * x)

int main() {
    double radius = 5.0;
    
    // Macro name PI and findSquare will be substituted
    // by preprocessor
    double area = PI * findSquare(radius);

    cout << area;
    return 0;
}

Output
78.5397

#undef Directive

The #undef preprocessor directive is used to undefined a previously defined macro (defined using #define). It is mainly used in the case when we want to redefine an existing macro or eliminate a macro definition associated with it from the code.

Syntax

#undef MACRO_NAME

Example

C++
#include <iostream>
using namespace std;

// Defining a macro
#define MAX_VALUE 100

int main()  {
    cout << MAX_VALUE << endl;

// using undef to change MAX_VALUE
#undef MAX_VALUE
#define MAX_VALUE 200

    cout << MAX_VALUE;
    return 0;
}

Output
100
200

Conditional Preprocessor Directives

The #if, #elif, #else, #endif, and #error are conditional preprocessor directives these are used for conditional compilation. These are used to include or exclude a code based on some conditions specified.

Syntax

#if condition
// code

#elif condition
// code

#else
// code

#endif

Example

C++
#include <iostream>
using namespace std;
#define PI 3.14159

int main() {

// Conditional compilation
#if defined(PI)
    cout << "PI is defined";
#elif defined(SQUARE)
    cout << "PI is not defined";
#else
#error "Neither PI nor SQUARE is defined"
#endif
    
    return 0;
}

Output
PI is defined

Explanation: This code uses preprocessor directives to check whether certain macros (PI and SQUARE) are defined. Since PI is defined, the program prints “PI is defined”, then checks if SQUARE is defined which is not so it doesn't print anything.

#ifdef and #ifndef Directives

The #ifdef and #ifndef are preprocessor directives that are used for conditional compilation. #ifndef verifies that a macro is not defined, #ifdef verifies that a macro is defined.

Syntax

#ifdef macro_name
// Code to be executed if macro_name is defined

#ifndef macro_name
// Code to be executed if macro_name is not defined
#endif

#ifdef and #ifndef are often used with the #endif directive to include or exclude portions of code based on whether a certain macro is defined or not.

Example

C++
#include <iostream>
using namespace std;

// Defining two macros
#define DEBUG
#define PI 3.14

int main() {

// Check if DEBUG is defined
#ifdef DEBUG
    cout << "Debug mode is ON" << endl;
#else
    cout << "Debug mode is OFF" << endl;
#endif

// Check if PI is defined
#ifndef PI
    cout << "PI is not defined" << endl;
#else
    cout << "PI is defined" << endl;
#endif

    return 0;
}

Output
Debug mode is ON
PI is defined

#error Directive

The #error directive is a preprocessor directive that is used to print a custom error message for compilation error. If any condition is not met or any particular requirement is not satisfied we can stop the compilation process using #error.

Syntax

#error error_message

Here, error_message is the custom error message that you want to print when the #error is encountered.

Example

C++
#include <iostream>
using namespace std;

// not defining PI here
// #define PI 3.14159

int main() {

#if defined(PI)
    cout << "PI is defined" << endl;
#else
#error "Neither PI nor SQUARE is defined"
#endif

    return 0;
}


Output

#error "Neither PI nor SQUARE is defined"

#warning Directive

The #warning preprocessor directive is used to generate a warning message during compilation. We can write custom warning messages generally used for any informational or debugging purpose.

Syntax

#warning message

Here, the message is any custom message that you want to print as an alert.

Example

C++
#include <iostream>
using namespace std;

// not defining it to trigger the warning
//#define PI 3.14

#ifndef PI
#warning "PI is not defined!"
#endif

int main() {
    cout << "Hey! geek";
    return 0;
}


Output

main.cpp:8:2: warning: #warning "PI is not defined!" [-Wcpp]
    8 | #warning "PI is not defined!"
      |  ^~~~~~~
Hey! geek

Note: The warning message is printed when the code is compiled to the compiler output or console. It is compiler dependent. Hence, how the warning is displayed depends on the compiler you are using.

#pragma Directive

The #pragma directive provides compiler-specific instructions to control compiler behavior such as warnings, optimizations, and header inclusion. Supported pragmas may vary between different compilers.

Syntax

#pragma directive

Commonly Used #pragma Flags

  • #pragma once: used to include guard for header files.
  • #pragma message: used to print custom messages at the time of compilation.
  • #pragma warning: used to control warning behaviour (like enable or disable warnings).
  • #pragma optimize: used to control optimization settings (manage optimization level).
  • #pragma comment: used to include some additional information in the object file (or specify linker options).

Example

C++
#include <iostream>
using namespace std;

#pragma once

// Defining PI to trigger a pragma message during
// compilation
#define PI 3.14

// to set aggressive optimization level
#pragma optimize("O3")

int main() {
#ifdef PI
#pragma message("YES! PI is defined.")
#endif
    cout << "In main function!\n";
    return 0;
}


Output

./Solution.cpp: In function 'int main()':
./Solution.cpp:15:38: note: #pragma message: YES! PI is defined.
 #pragma message("YES! PI is defined.")
Comment