Open In App

Macros In C++

Last Updated : 11 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

C++ is a powerful and versatile programming language that offers many features to enhance code flexibility and maintainability. One such feature is macros, which are preprocessor directives used for code generation and substitution. Macros are an essential part of C++ programming and play a crucial role in simplifying code, making it more readable and efficient. In this article, we will learn about the macros in C++.

What are Macros?

In C++, a macro is part of code that is expanded to its value. Macros are defined using the #define directive. They provide a way to create symbolic constants and code snippets that can be reused throughout a program. Macros are processed by the C++ preprocessor, which runs before the actual compilation. During preprocessing, macros are replaced with their corresponding values, making it an effective tool for code generation and simplification.

Syntax

The syntax for defining a macro in C++ is as follows:

#define MACRO_NAME macro_definition
  • MACRO_NAME: It is the name we give to the macro, that’s usually in uppercase to differentiate it from ordinary C++ identifiers.
  • macro_definition: It is the code that the preprocessor will substitute whenever the macro is used.

Example of Macro

Let’s explore a simple example of a macro in C++. Suppose we want to create a macro to calculate the square of a number. Here’s how we can define and use a macro:

C++




// C++ program to illustrate the macro definition
#include <iostream>
using namespace std;
  
// Define a macro to calculate the square of a number
#define SQUARE(x) (x * x)
  
int main()
{
    int n = 7;
    int result = SQUARE(n); // Expands to: (n * n)
    cout << "Square of " << n << " is " << result;
    return 0;
}


Output

Square of 7 is 49

Explanation

In this example, the #define directive defines a macro named SQUARE(x) that takes an argument x and returns the square of that value. When we use SQUARE(n), it is expanded to (n * n) during preprocessing.

Types of Macros in C++

Macros can be classified into four types in C++:

  1. Object-Like Macros
  2. Function-Like Macros
  3. Multiline Macros
  4. Chain Macros

1. Object-Like Macros

Object-like macros are simple macros that act as textual replacements. They are typically used for defining constants or short, reusable code snippets. These macros do not take arguments.

Example:

In this example, PI is defined as an object-like macro, and whenever PI appears in the code, it is replaced with the value 3.14159.

C++




// C++ program to illustrate the object like macros
#include <iostream>
using namespace std;
  
// Define a constant for the value of PI
#define PI 3.14159
  
int main()
{
    double radius = 4.0;
  
    // Calculate the area of the circle
    double area = PI * radius * radius;
  
    cout << "Area of circle with radius " << radius
         << " is " << area;
  
    return 0;
}


Output

Area of circle with radius 4 is 50.2654

2. Function-Like Macros

Function-like macros can take arguments and perform text substitution based on those arguments. They are used for creating inline functions or code snippets, but they lack type safety.

Example:

In this example, PRINT(x) is a function-like macro that takes an argument x and expands to a function that prints the value of x.

C++




// C++ program to illustrate the function like macros
#include <iostream>
using namespace std;
  
// Define a macro to print a value
#define PRINT(x) cout << "Value is: " << x
  
int main()
{
    int value = 42;
  
    // Print the value using the PRINT macro
    PRINT(value);
    return 0;
}


Output

Value is: 42

3. Multiline Macros

Multiline macros are macros that allow us to define multiple lines of code as a single macro. They are useful for encapsulating complex code blocks, improving code readability, and reducing code duplication.

For defining multiline macros, we need to append the ( \ ) backslash after every line.

Example:

In this example, we have defined a multiline macro named PRINT_RECTANGLE that takes two parameters: width and height. The macro is used to print a rectangular pattern of asterisks (‘*’).

C++




// C++ program to illustrate the multiline macros
#include <iostream>
  
// Define a macro for printing a rectangle with a given
// width and height
#define PRINT_RECTANGLE(width, height)                     \
    for (int i = 0; i < height; i++) {                     \
        for (int j = 0; j < width; j++) {                  \
            std::cout << "*";                              \
        }                                                  \
        std::cout << std::endl;                            \
    }
  
int main()
{
  
    // Print a rectangle with a width of 4 and a height of 3
    PRINT_RECTANGLE(4, 3);
    return 0;
}


Output

****
****
****

4. Chain Macros

The chain macros are those macros that expand to another macro definition. For example, in a macro definition in which another macro is defined, the parent macro will be expanded first and then the child macro will be expanded.

Example

In this example, we will define a macro named CLERK with value 10 and another macro named WORKER with value CLERK. We will then use cout to see which value is printed using worker macro.

C++




// C++ program to illustrate the chain macros
#include <iostream>
using namespace std;
  
// defining first macro
#define CLERK 10
  
// defining second macro
#define WORKER CLERK
  
int main()
{
  
    // checking value of worker
    cout << WORKER;
    
    return 0;
}


Output

10

10 is printed. It means that the macro expansion of WORKER will go like this: WORKER -> CLERK -> 10.

Predefined Macros

Predefined macros are built-in macros provided by the C++ preprocessor. They convey information about the code, such as the current line number, source file name, and compilation date. These macros are automatically defined by the compiler and can be useful for debugging and logging purposes.

The following are some commonly used predefined macros in C++:

  1. __LINE__: This macro expands to the current line number in the source code.
  2. __FILE__: This macro expands to the name of the current source file.
  3. __DATE__: This macro expands to a string that represents the date of compilation.
  4. __TIME__: This macro expands to a string that represents the time of compilation.

Example

In this example, __LINE__ is replaced with the current line number, __FILE__ with the source file name and __DATE__ with the compilation date. These can be handy for debugging and logging.

C++




// C++ program to illustrate the predefined macros
#include <iostream>
using namespace std;
  
int main()
{
  
    // Display the current line number and the source file
    // name
    cout << "This is line " << __LINE__ << " in file "
         << __FILE__ << "\n";
  
    // Display the compilation date
    cout << "Compiled on " << __DATE__;
  
    return 0;
}


Output

This is line 10 in file ./Solution.cpp
Compiled on Nov  7 2023

Advantages of Macros

The advantages of Macros are mentioned below:

  1. Code Reusability: Macros allow us to define reusable code snippets or constants, making our code more maintainable and DRY (Don’t Repeat Yourself).
  2. Code Generation: Macros are expanded before the compilation during preprocessing which can be helpful in generation of code in the program.
  3. Conditional Compilation: Macros are often used in conjunction with conditional compilation directives like #ifdef and #ifndef to control which parts of code are included in the compilation.
  4. Enhanced Readability: Macros can make our code more readable by providing meaningful names for constants and code snippets at the start of the program.

Disadvantages of Macros

The disadvantages of Macros are mentioned below:

  1. Lack of Type Safety: Macros don’t have type information, so they can lead to unexpected behavior if used with incorrect types, whereas using constants and inline functions provides better type safety.
  2. Debugging Challenges: Debugging code with macros can be challenging, as the expanded macro code is not directly visible in the debugging process. This can make it harder to identify issues in the code.
  3. Readability and Maintainability: Overuse of macros, especially complex macros, can decrease code readability and maintainability. Code can become difficult to understand when macros are used excessively.
  4. Limited Functionality: Macros are limited in their capabilities compared to modern C++ features like inline functions, constexpr variables, and templates. Using these features can often lead to more efficient and type-safe code.

Conclusion

Macros in C++ can be a beneficial tool for creating constants, code snippets, or for conditional compilation. However, they come with their very own set of disadvantages, inclusive of potential issues with type safety, debugging, and maintainability. In modern C++, high-quality practices regularly propose the use of alternatives like constants, inline functions, and templates to attain the same goals whilst keeping code quality, readability, and type safety.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads