#define in C++

Last Updated : 27 Oct, 2026

#define is a preprocessor directive used to define macros. It allows programmers to assign a name to a constant value or a piece of code. Before compilation, the preprocessor replaces occurrences of the macro name with its defined replacement text.

  • #define is commonly used to define symbolic constants and function-like macros.
  • It performs text substitution during preprocessing, before the actual compilation.
  • Unlike variables and functions, macros do not provide type checking.

Example: Program to define a constant value and calculate the area of a circle using #define.

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

#define PI 3.14159

int main(){
    
    double radius = 5;

    double area = PI * radius * radius;

    cout << "Area of Circle: " << area;

    return 0;
}

Output
Area of Circle: 78.5397

Explanation:

  • The #define PI 3.14159 directive defines a macro named PI.
  • During preprocessing, each occurrence of PI is replaced with 3.14159.
  • The program calculates the area using the formula PI * radius * radius.

Syntax

The #define directive is written using the following syntax:

#define MACRO_NAME replacement_text

Here:

  • #define: Preprocessor directive used to define a macro.
  • MACRO_NAME: Name of the macro, generally written in uppercase.
  • replacement_text: Value or code that replaces the macro name.

Example:

#define PI 3.14159

Whenever PI appears in the source code in a context where the macro is expanded, the preprocessor replaces it with 3.14159.

Note: The #define directive does not require a semicolon (;) at the end.

Types of Macros

The #define directive is mainly used to create two types of macros.

1. Object-Like Macros

Object-like macros define a name that represents a fixed value or replacement text. They are commonly used for constants.

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

#define MAX_SIZE 100

int main(){
    
    cout << "Maximum Size: " << MAX_SIZE;

    return 0;
}

Output
Maximum Size: 100

Explanation: The preprocessor replaces MAX_SIZE with 100 before compilation.

2. Function-Like Macros

Function-like macros accept arguments and replace them with a predefined expression. They resemble functions but are expanded by the preprocessor.

Syntax:

#define MACRO_NAME(parameters) expression

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

#define SQUARE(x) ((x) * (x))

int main(){
    
    int num = 5;

    cout << "Square: " << SQUARE(num);

    return 0;
}

Output
Square: 25

Explanation: The macro SQUARE(num) expands to ((num) * (num)), which calculates the square of the number.

Note: Parentheses are important in function-like macros to avoid operator-precedence issues. However, macros can still evaluate their arguments multiple times, so inline functions are generally safer.

How Does #define Work

The #define directive works during the preprocessing stage, before the compiler translates C++ code into machine code.

  • The preprocessor reads the #define directive and stores the macro definition.
  • When it encounters the macro name, it expands it using the defined replacement text.
  • The resulting code is then passed to the compiler.

For example:

Original code:

#define VALUE 10
int result = VALUE * 2;

After preprocessing:

int result = 10 * 2;

The compiler processes the expanded code.

Conditional Compilation Using #define

The #define directive can also be used with conditional preprocessing directives such as #ifdef, #ifndef, and #endif. These directives allow specific sections of code to be included or excluded based on whether a macro is defined.

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

#define DEBUG

int main(){

#ifdef DEBUG
    cout << "Debug mode is enabled" << endl;
#endif

    cout << "Program is running";

    return 0;
}

Output
Debug mode is enabled
Program is running

Explanation:

  • #define DEBUG defines the DEBUG macro without assigning a value.
  • #ifdef DEBUG checks whether the macro is defined.
  • Since DEBUG is defined, the statement inside the conditional block is included during compilation.

Undefining a Macro Using #undef

The #undef directive removes an existing macro definition. After it is undefined, the macro name is no longer replaced by the preprocessor unless it is defined again.

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

#define VALUE 50

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

#undef VALUE
#define VALUE 100

    cout << VALUE;

    return 0;
}

Output
50
100

Explanation: Initially, VALUE is defined as 50. After #undef, it is redefined as 100, so the second output displays the updated value.

Advantages of #define

  • Allows symbolic names to replace repeated literal values.
  • Supports conditional compilation for debugging and platform-specific code.
  • Can define reusable code fragments through function-like macros.

Limitations of #define

  • Does not provide type checking or respect normal C++ scope rules.
  • Function-like macros may produce unexpected results due to operator precedence or repeated argument evaluation.
  • Macro expansion can make debugging and error messages more difficult to understand.
Comment